mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-20 20:55:50 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
825726c883 | ||
|
|
54e63d88d4 | ||
|
|
4018c97cb6 | ||
|
|
d0b029f995 | ||
|
|
aabe6d11b2 | ||
|
|
181cc37744 | ||
|
|
cd78f5c02c |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -60,7 +60,7 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Install Rust
|
- name: Install Rust
|
||||||
uses: dtolnay/rust-toolchain@1.83.0
|
uses: dtolnay/rust-toolchain@1.88.0
|
||||||
|
|
||||||
- name: Restore Rust Cache
|
- name: Restore Rust Cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
|
|||||||
978
CHANGELOG.md
978
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
98
Cargo.lock
generated
98
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
@@ -243,7 +243,7 @@ checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
@@ -665,9 +665,9 @@ version = "0.3.30"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 2.0.52",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1033,6 +1033,15 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonc-parser"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ec4ac49f13c7b00f435f8a5bb55d725705e2cf620df35a5859321595102eb7e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel32-sys"
|
name = "kernel32-sys"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -1393,9 +1402,9 @@ checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_meta",
|
"pest_meta",
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 2.0.52",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1478,7 +1487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-error-attr",
|
"proc-macro-error-attr",
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
"version_check",
|
"version_check",
|
||||||
@@ -1490,7 +1499,7 @@ version = "1.0.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
@@ -1518,9 +1527,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.78"
|
version = "1.0.103"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -1542,7 +1551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 2.0.52",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1560,7 +1569,7 @@ version = "1.0.35"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1655,9 +1664,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rbx_reflection_database"
|
name = "rbx_reflection_database"
|
||||||
version = "2.0.0+roblox-694"
|
version = "2.0.1+roblox-697"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "844ceb61f23bad59b06d7299b69ff276579316eafa9857981da3012a6223f663"
|
checksum = "d69035a14b103c5a9b8bc6a61d30f4ee6f2608afdee137dae09b26037dba5dc8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dirs 5.0.1",
|
"dirs 5.0.1",
|
||||||
"log",
|
"log",
|
||||||
@@ -1884,7 +1893,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rojo"
|
name = "rojo"
|
||||||
version = "7.6.0"
|
version = "7.6.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
@@ -1903,6 +1912,7 @@ dependencies = [
|
|||||||
"hyper",
|
"hyper",
|
||||||
"insta",
|
"insta",
|
||||||
"jod-thread",
|
"jod-thread",
|
||||||
|
"jsonc-parser",
|
||||||
"log",
|
"log",
|
||||||
"maplit",
|
"maplit",
|
||||||
"memofs",
|
"memofs",
|
||||||
@@ -2054,10 +2064,11 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.197"
|
version = "1.0.228"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2072,25 +2083,36 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_core"
|
||||||
version = "1.0.197"
|
version = "1.0.228"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 2.0.52",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.114"
|
version = "1.0.145"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
|
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
|
"memchr",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2195,18 +2217,18 @@ version = "1.0.109"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.52"
|
version = "2.0.108"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
|
checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -2289,9 +2311,9 @@ version = "1.0.57"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 2.0.52",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2401,9 +2423,9 @@ version = "0.1.27"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 2.0.52",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2638,9 +2660,9 @@ dependencies = [
|
|||||||
"bumpalo",
|
"bumpalo",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 2.0.52",
|
"syn 2.0.108",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2672,9 +2694,9 @@ version = "0.2.92"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 2.0.52",
|
"syn 2.0.108",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
@@ -2970,9 +2992,9 @@ version = "0.7.35"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.78",
|
"proc-macro2 1.0.103",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
"syn 2.0.52",
|
"syn 2.0.108",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rojo"
|
name = "rojo"
|
||||||
version = "7.6.0"
|
version = "7.6.1"
|
||||||
rust-version = "1.83"
|
rust-version = "1.88"
|
||||||
authors = [
|
authors = [
|
||||||
"Lucien Greathouse <me@lpghatguy.com>",
|
"Lucien Greathouse <me@lpghatguy.com>",
|
||||||
"Micah Reid <git@dekkonot.com>",
|
"Micah Reid <git@dekkonot.com>",
|
||||||
@@ -58,7 +58,7 @@ memofs = { version = "0.3.0", path = "crates/memofs" }
|
|||||||
rbx_binary = "2.0.0"
|
rbx_binary = "2.0.0"
|
||||||
rbx_dom_weak = "4.0.0"
|
rbx_dom_weak = "4.0.0"
|
||||||
rbx_reflection = "6.0.0"
|
rbx_reflection = "6.0.0"
|
||||||
rbx_reflection_database = "2.0.0"
|
rbx_reflection_database = "2.0.1"
|
||||||
rbx_xml = "2.0.0"
|
rbx_xml = "2.0.0"
|
||||||
|
|
||||||
anyhow = "1.0.80"
|
anyhow = "1.0.80"
|
||||||
@@ -85,7 +85,8 @@ reqwest = { version = "0.11.24", default-features = false, features = [
|
|||||||
ritz = "0.1.0"
|
ritz = "0.1.0"
|
||||||
roblox_install = "1.0.0"
|
roblox_install = "1.0.0"
|
||||||
serde = { version = "1.0.197", features = ["derive", "rc"] }
|
serde = { version = "1.0.197", features = ["derive", "rc"] }
|
||||||
serde_json = "1.0.114"
|
serde_json = "1.0.145"
|
||||||
|
jsonc-parser = { version = "0.27.0", features = ["serde"] }
|
||||||
toml = "0.5.11"
|
toml = "0.5.11"
|
||||||
termcolor = "1.4.1"
|
termcolor = "1.4.1"
|
||||||
thiserror = "1.0.57"
|
thiserror = "1.0.57"
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions fo
|
|||||||
|
|
||||||
Pull requests are welcome!
|
Pull requests are welcome!
|
||||||
|
|
||||||
Rojo supports Rust 1.83 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has.
|
Rojo supports Rust 1.88 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details.
|
Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details.
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
# Roblox Studio lock files
|
# Roblox Studio lock files
|
||||||
/*.rbxlx.lock
|
/*.rbxlx.lock
|
||||||
/*.rbxl.lock
|
/*.rbxl.lock
|
||||||
|
|
||||||
|
sourcemap.json
|
||||||
|
|||||||
@@ -3,4 +3,6 @@
|
|||||||
|
|
||||||
# Roblox Studio lock files
|
# Roblox Studio lock files
|
||||||
/*.rbxlx.lock
|
/*.rbxlx.lock
|
||||||
/*.rbxl.lock
|
/*.rbxl.lock
|
||||||
|
|
||||||
|
sourcemap.json
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
# Plugin model files
|
# Plugin model files
|
||||||
/{project_name}.rbxmx
|
/{project_name}.rbxmx
|
||||||
/{project_name}.rbxm
|
/{project_name}.rbxm
|
||||||
|
|
||||||
|
sourcemap.json
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
7.6.0
|
7.6.1
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"Version": [
|
"Version": [
|
||||||
0,
|
0,
|
||||||
694,
|
697,
|
||||||
0,
|
0,
|
||||||
6940982
|
6970925
|
||||||
],
|
],
|
||||||
"Classes": {
|
"Classes": {
|
||||||
"Accessory": {
|
"Accessory": {
|
||||||
@@ -550,6 +550,9 @@
|
|||||||
"Scale": {
|
"Scale": {
|
||||||
"Float32": 1.0
|
"Float32": 1.0
|
||||||
},
|
},
|
||||||
|
"SlimHash": {
|
||||||
|
"SharedString": ""
|
||||||
|
},
|
||||||
"SourceAssetId": {
|
"SourceAssetId": {
|
||||||
"Int64": -1
|
"Int64": -1
|
||||||
},
|
},
|
||||||
@@ -1975,6 +1978,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"AnimationGraphDefinition": {
|
||||||
|
"Name": "AnimationGraphDefinition",
|
||||||
|
"Tags": [],
|
||||||
|
"Superclass": "AnimationClip",
|
||||||
|
"Properties": {},
|
||||||
|
"DefaultProperties": {
|
||||||
|
"Archivable": {
|
||||||
|
"Bool": true
|
||||||
|
},
|
||||||
|
"Attributes": {
|
||||||
|
"Attributes": {}
|
||||||
|
},
|
||||||
|
"Capabilities": {
|
||||||
|
"SecurityCapabilities": 0
|
||||||
|
},
|
||||||
|
"GuidBinaryString": {
|
||||||
|
"BinaryString": "AAAAAAAAAAAAAAAAAAAAAA=="
|
||||||
|
},
|
||||||
|
"HistoryId": {
|
||||||
|
"UniqueId": "00000000000000000000000000000000"
|
||||||
|
},
|
||||||
|
"Loop": {
|
||||||
|
"Bool": true
|
||||||
|
},
|
||||||
|
"Priority": {
|
||||||
|
"Enum": 2
|
||||||
|
},
|
||||||
|
"Sandboxed": {
|
||||||
|
"Bool": false
|
||||||
|
},
|
||||||
|
"SourceAssetId": {
|
||||||
|
"Int64": -1
|
||||||
|
},
|
||||||
|
"Tags": {
|
||||||
|
"Tags": []
|
||||||
|
},
|
||||||
|
"UniqueId": {
|
||||||
|
"UniqueId": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"AnimationImportData": {
|
"AnimationImportData": {
|
||||||
"Name": "AnimationImportData",
|
"Name": "AnimationImportData",
|
||||||
"Tags": [
|
"Tags": [
|
||||||
@@ -1995,6 +2039,84 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"AnimationNode": {
|
||||||
|
"Name": "AnimationNode",
|
||||||
|
"Tags": [
|
||||||
|
"NotCreatable",
|
||||||
|
"NotReplicated"
|
||||||
|
],
|
||||||
|
"Superclass": "Object",
|
||||||
|
"Properties": {},
|
||||||
|
"DefaultProperties": {}
|
||||||
|
},
|
||||||
|
"AnimationNodeDefinition": {
|
||||||
|
"Name": "AnimationNodeDefinition",
|
||||||
|
"Tags": [],
|
||||||
|
"Superclass": "Instance",
|
||||||
|
"Properties": {
|
||||||
|
"InputPinData": {
|
||||||
|
"Name": "InputPinData",
|
||||||
|
"Scriptability": "None",
|
||||||
|
"DataType": {
|
||||||
|
"Value": "BinaryString"
|
||||||
|
},
|
||||||
|
"Tags": [
|
||||||
|
"Hidden",
|
||||||
|
"NotScriptable"
|
||||||
|
],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "Serializes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NodeType": {
|
||||||
|
"Name": "NodeType",
|
||||||
|
"Scriptability": "ReadWrite",
|
||||||
|
"DataType": {
|
||||||
|
"Enum": "AnimationNodeType"
|
||||||
|
},
|
||||||
|
"Tags": [],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "Serializes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DefaultProperties": {
|
||||||
|
"Archivable": {
|
||||||
|
"Bool": true
|
||||||
|
},
|
||||||
|
"Attributes": {
|
||||||
|
"Attributes": {}
|
||||||
|
},
|
||||||
|
"Capabilities": {
|
||||||
|
"SecurityCapabilities": 0
|
||||||
|
},
|
||||||
|
"HistoryId": {
|
||||||
|
"UniqueId": "00000000000000000000000000000000"
|
||||||
|
},
|
||||||
|
"InputPinData": {
|
||||||
|
"BinaryString": ""
|
||||||
|
},
|
||||||
|
"NodeType": {
|
||||||
|
"Enum": 0
|
||||||
|
},
|
||||||
|
"Sandboxed": {
|
||||||
|
"Bool": false
|
||||||
|
},
|
||||||
|
"SourceAssetId": {
|
||||||
|
"Int64": -1
|
||||||
|
},
|
||||||
|
"Tags": {
|
||||||
|
"Tags": []
|
||||||
|
},
|
||||||
|
"UniqueId": {
|
||||||
|
"UniqueId": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"AnimationRigData": {
|
"AnimationRigData": {
|
||||||
"Name": "AnimationRigData",
|
"Name": "AnimationRigData",
|
||||||
"Tags": [],
|
"Tags": [],
|
||||||
@@ -6332,9 +6454,7 @@
|
|||||||
},
|
},
|
||||||
"AudioSpeechToText": {
|
"AudioSpeechToText": {
|
||||||
"Name": "AudioSpeechToText",
|
"Name": "AudioSpeechToText",
|
||||||
"Tags": [
|
"Tags": [],
|
||||||
"NotBrowsable"
|
|
||||||
],
|
|
||||||
"Superclass": "Instance",
|
"Superclass": "Instance",
|
||||||
"Properties": {
|
"Properties": {
|
||||||
"Enabled": {
|
"Enabled": {
|
||||||
@@ -21030,7 +21150,7 @@
|
|||||||
"NotBrowsable",
|
"NotBrowsable",
|
||||||
"NotCreatable",
|
"NotCreatable",
|
||||||
"NotReplicated",
|
"NotReplicated",
|
||||||
"Settings"
|
"Service"
|
||||||
],
|
],
|
||||||
"Superclass": "Instance",
|
"Superclass": "Instance",
|
||||||
"Properties": {
|
"Properties": {
|
||||||
@@ -23979,6 +24099,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"EncodingService": {
|
||||||
|
"Name": "EncodingService",
|
||||||
|
"Tags": [
|
||||||
|
"NotCreatable",
|
||||||
|
"NotReplicated",
|
||||||
|
"Service"
|
||||||
|
],
|
||||||
|
"Superclass": "Instance",
|
||||||
|
"Properties": {},
|
||||||
|
"DefaultProperties": {
|
||||||
|
"Archivable": {
|
||||||
|
"Bool": true
|
||||||
|
},
|
||||||
|
"HistoryId": {
|
||||||
|
"UniqueId": "00000000000000000000000000000000"
|
||||||
|
},
|
||||||
|
"UniqueId": {
|
||||||
|
"UniqueId": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"EqualizerSoundEffect": {
|
"EqualizerSoundEffect": {
|
||||||
"Name": "EqualizerSoundEffect",
|
"Name": "EqualizerSoundEffect",
|
||||||
"Tags": [],
|
"Tags": [],
|
||||||
@@ -24135,27 +24276,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ExampleService": {
|
|
||||||
"Name": "ExampleService",
|
|
||||||
"Tags": [
|
|
||||||
"NotCreatable",
|
|
||||||
"NotReplicated",
|
|
||||||
"Service"
|
|
||||||
],
|
|
||||||
"Superclass": "Instance",
|
|
||||||
"Properties": {},
|
|
||||||
"DefaultProperties": {
|
|
||||||
"Archivable": {
|
|
||||||
"Bool": true
|
|
||||||
},
|
|
||||||
"HistoryId": {
|
|
||||||
"UniqueId": "00000000000000000000000000000000"
|
|
||||||
},
|
|
||||||
"UniqueId": {
|
|
||||||
"UniqueId": "00000000000000000000000000000000"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ExampleV2Service": {
|
"ExampleV2Service": {
|
||||||
"Name": "ExampleV2Service",
|
"Name": "ExampleV2Service",
|
||||||
"Tags": [
|
"Tags": [
|
||||||
@@ -26293,6 +26413,9 @@
|
|||||||
"Scale": {
|
"Scale": {
|
||||||
"Float32": 1.0
|
"Float32": 1.0
|
||||||
},
|
},
|
||||||
|
"SlimHash": {
|
||||||
|
"SharedString": ""
|
||||||
|
},
|
||||||
"SourceAssetId": {
|
"SourceAssetId": {
|
||||||
"Int64": -1
|
"Int64": -1
|
||||||
},
|
},
|
||||||
@@ -27586,7 +27709,7 @@
|
|||||||
"NotBrowsable",
|
"NotBrowsable",
|
||||||
"NotCreatable",
|
"NotCreatable",
|
||||||
"NotReplicated",
|
"NotReplicated",
|
||||||
"Settings"
|
"Service"
|
||||||
],
|
],
|
||||||
"Superclass": "Instance",
|
"Superclass": "Instance",
|
||||||
"Properties": {
|
"Properties": {
|
||||||
@@ -32260,6 +32383,9 @@
|
|||||||
"Scale": {
|
"Scale": {
|
||||||
"Float32": 1.0
|
"Float32": 1.0
|
||||||
},
|
},
|
||||||
|
"SlimHash": {
|
||||||
|
"SharedString": ""
|
||||||
|
},
|
||||||
"SourceAssetId": {
|
"SourceAssetId": {
|
||||||
"Int64": -1
|
"Int64": -1
|
||||||
},
|
},
|
||||||
@@ -41477,6 +41603,22 @@
|
|||||||
"Serialization": "DoesNotSerialize"
|
"Serialization": "DoesNotSerialize"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"IsSlimEnabled": {
|
||||||
|
"Name": "IsSlimEnabled",
|
||||||
|
"Scriptability": "None",
|
||||||
|
"DataType": {
|
||||||
|
"Value": "Bool"
|
||||||
|
},
|
||||||
|
"Tags": [
|
||||||
|
"Hidden",
|
||||||
|
"NotScriptable"
|
||||||
|
],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "DoesNotSerialize"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DefaultProperties": {
|
"DefaultProperties": {
|
||||||
@@ -41593,7 +41735,7 @@
|
|||||||
"Tags": [
|
"Tags": [
|
||||||
"NotCreatable",
|
"NotCreatable",
|
||||||
"NotReplicated",
|
"NotReplicated",
|
||||||
"Settings"
|
"Service"
|
||||||
],
|
],
|
||||||
"Superclass": "Instance",
|
"Superclass": "Instance",
|
||||||
"Properties": {},
|
"Properties": {},
|
||||||
@@ -42203,6 +42345,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"EmissiveFilePath": {
|
||||||
|
"Name": "EmissiveFilePath",
|
||||||
|
"Scriptability": "ReadWrite",
|
||||||
|
"DataType": {
|
||||||
|
"Value": "String"
|
||||||
|
},
|
||||||
|
"Tags": [],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "Serializes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"IsPbr": {
|
"IsPbr": {
|
||||||
"Name": "IsPbr",
|
"Name": "IsPbr",
|
||||||
"Scriptability": "Read",
|
"Scriptability": "Read",
|
||||||
@@ -45055,7 +45210,7 @@
|
|||||||
"Name": "SlimHash",
|
"Name": "SlimHash",
|
||||||
"Scriptability": "None",
|
"Scriptability": "None",
|
||||||
"DataType": {
|
"DataType": {
|
||||||
"Value": "BinaryString"
|
"Value": "SharedString"
|
||||||
},
|
},
|
||||||
"Tags": [
|
"Tags": [
|
||||||
"Hidden",
|
"Hidden",
|
||||||
@@ -45063,7 +45218,7 @@
|
|||||||
],
|
],
|
||||||
"Kind": {
|
"Kind": {
|
||||||
"Canonical": {
|
"Canonical": {
|
||||||
"Serialization": "DoesNotSerialize"
|
"Serialization": "Serializes"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -45163,6 +45318,9 @@
|
|||||||
"Scale": {
|
"Scale": {
|
||||||
"Float32": 1.0
|
"Float32": 1.0
|
||||||
},
|
},
|
||||||
|
"SlimHash": {
|
||||||
|
"SharedString": ""
|
||||||
|
},
|
||||||
"SourceAssetId": {
|
"SourceAssetId": {
|
||||||
"Int64": -1
|
"Int64": -1
|
||||||
},
|
},
|
||||||
@@ -50221,7 +50379,7 @@
|
|||||||
"Tags": [
|
"Tags": [
|
||||||
"NotCreatable",
|
"NotCreatable",
|
||||||
"NotReplicated",
|
"NotReplicated",
|
||||||
"Settings"
|
"Service"
|
||||||
],
|
],
|
||||||
"Superclass": "Instance",
|
"Superclass": "Instance",
|
||||||
"Properties": {
|
"Properties": {
|
||||||
@@ -51305,6 +51463,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ChatAvailabilityStatus": {
|
||||||
|
"Name": "ChatAvailabilityStatus",
|
||||||
|
"Scriptability": "None",
|
||||||
|
"DataType": {
|
||||||
|
"Value": "String"
|
||||||
|
},
|
||||||
|
"Tags": [
|
||||||
|
"Hidden",
|
||||||
|
"NotReplicated"
|
||||||
|
],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "DoesNotSerialize"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ChatMode": {
|
"ChatMode": {
|
||||||
"Name": "ChatMode",
|
"Name": "ChatMode",
|
||||||
"Scriptability": "None",
|
"Scriptability": "None",
|
||||||
@@ -51568,10 +51742,12 @@
|
|||||||
"DataType": {
|
"DataType": {
|
||||||
"Value": "Bool"
|
"Value": "Bool"
|
||||||
},
|
},
|
||||||
"Tags": [],
|
"Tags": [
|
||||||
|
"Hidden"
|
||||||
|
],
|
||||||
"Kind": {
|
"Kind": {
|
||||||
"Canonical": {
|
"Canonical": {
|
||||||
"Serialization": "Serializes"
|
"Serialization": "DoesNotSerialize"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -53409,6 +53585,23 @@
|
|||||||
],
|
],
|
||||||
"Superclass": "LayerCollector",
|
"Superclass": "LayerCollector",
|
||||||
"Properties": {
|
"Properties": {
|
||||||
|
"Plugin": {
|
||||||
|
"Name": "Plugin",
|
||||||
|
"Scriptability": "None",
|
||||||
|
"DataType": {
|
||||||
|
"Value": "Ref"
|
||||||
|
},
|
||||||
|
"Tags": [
|
||||||
|
"Hidden",
|
||||||
|
"NotReplicated",
|
||||||
|
"ReadOnly"
|
||||||
|
],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "DoesNotSerialize"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Title": {
|
"Title": {
|
||||||
"Name": "Title",
|
"Name": "Title",
|
||||||
"Scriptability": "ReadWrite",
|
"Scriptability": "ReadWrite",
|
||||||
@@ -58013,6 +58206,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"FrameNumber": {
|
||||||
|
"Name": "FrameNumber",
|
||||||
|
"Scriptability": "Read",
|
||||||
|
"DataType": {
|
||||||
|
"Value": "Int64"
|
||||||
|
},
|
||||||
|
"Tags": [
|
||||||
|
"NotReplicated",
|
||||||
|
"ReadOnly"
|
||||||
|
],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "DoesNotSerialize"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"PredictionState": {
|
"PredictionState": {
|
||||||
"Name": "PredictionState",
|
"Name": "PredictionState",
|
||||||
"Scriptability": "Read",
|
"Scriptability": "Read",
|
||||||
@@ -58043,22 +58252,6 @@
|
|||||||
"Serialization": "DoesNotSerialize"
|
"Serialization": "DoesNotSerialize"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"ServerFrame": {
|
|
||||||
"Name": "ServerFrame",
|
|
||||||
"Scriptability": "Read",
|
|
||||||
"DataType": {
|
|
||||||
"Value": "Int64"
|
|
||||||
},
|
|
||||||
"Tags": [
|
|
||||||
"NotReplicated",
|
|
||||||
"ReadOnly"
|
|
||||||
],
|
|
||||||
"Kind": {
|
|
||||||
"Canonical": {
|
|
||||||
"Serialization": "DoesNotSerialize"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DefaultProperties": {
|
"DefaultProperties": {
|
||||||
@@ -66735,6 +66928,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"DefaultScriptSyncFileType": {
|
||||||
|
"Name": "DefaultScriptSyncFileType",
|
||||||
|
"Scriptability": "None",
|
||||||
|
"DataType": {
|
||||||
|
"Enum": "DefaultScriptSyncFileType"
|
||||||
|
},
|
||||||
|
"Tags": [],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "Serializes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"DeprecatedObjectsShown": {
|
"DeprecatedObjectsShown": {
|
||||||
"Name": "DeprecatedObjectsShown",
|
"Name": "DeprecatedObjectsShown",
|
||||||
"Scriptability": "ReadWrite",
|
"Scriptability": "ReadWrite",
|
||||||
@@ -74683,7 +74889,7 @@
|
|||||||
"SecurityCapabilities": 0
|
"SecurityCapabilities": 0
|
||||||
},
|
},
|
||||||
"ChatTranslationFTUXShown": {
|
"ChatTranslationFTUXShown": {
|
||||||
"Bool": true
|
"Bool": false
|
||||||
},
|
},
|
||||||
"ChatTranslationToggleEnabled": {
|
"ChatTranslationToggleEnabled": {
|
||||||
"Bool": false
|
"Bool": false
|
||||||
@@ -76244,6 +76450,9 @@
|
|||||||
"Scale": {
|
"Scale": {
|
||||||
"Float32": 1.0
|
"Float32": 1.0
|
||||||
},
|
},
|
||||||
|
"SlimHash": {
|
||||||
|
"SharedString": ""
|
||||||
|
},
|
||||||
"SourceAssetId": {
|
"SourceAssetId": {
|
||||||
"Int64": -1
|
"Int64": -1
|
||||||
},
|
},
|
||||||
@@ -80533,7 +80742,7 @@
|
|||||||
"Tags": [
|
"Tags": [
|
||||||
"NotCreatable",
|
"NotCreatable",
|
||||||
"NotReplicated",
|
"NotReplicated",
|
||||||
"UserSettings"
|
"Service"
|
||||||
],
|
],
|
||||||
"Superclass": "Instance",
|
"Superclass": "Instance",
|
||||||
"Properties": {
|
"Properties": {
|
||||||
@@ -82451,6 +82660,90 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ValueCurve": {
|
||||||
|
"Name": "ValueCurve",
|
||||||
|
"Tags": [],
|
||||||
|
"Superclass": "Instance",
|
||||||
|
"Properties": {
|
||||||
|
"Length": {
|
||||||
|
"Name": "Length",
|
||||||
|
"Scriptability": "Read",
|
||||||
|
"DataType": {
|
||||||
|
"Value": "Int32"
|
||||||
|
},
|
||||||
|
"Tags": [
|
||||||
|
"NotReplicated",
|
||||||
|
"ReadOnly"
|
||||||
|
],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "DoesNotSerialize"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ValueType": {
|
||||||
|
"Name": "ValueType",
|
||||||
|
"Scriptability": "Read",
|
||||||
|
"DataType": {
|
||||||
|
"Value": "String"
|
||||||
|
},
|
||||||
|
"Tags": [
|
||||||
|
"NotReplicated",
|
||||||
|
"ReadOnly"
|
||||||
|
],
|
||||||
|
"Kind": {
|
||||||
|
"Canonical": {
|
||||||
|
"Serialization": "DoesNotSerialize"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ValuesAndTimes": {
|
||||||
|
"Name": "ValuesAndTimes",
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
"Tags": {
|
||||||
|
"Tags": []
|
||||||
|
},
|
||||||
|
"UniqueId": {
|
||||||
|
"UniqueId": "00000000000000000000000000000000"
|
||||||
|
},
|
||||||
|
"ValuesAndTimes": {
|
||||||
|
"BinaryString": "AgAAAAAAAAABAAAAAAAAAA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Vector3Curve": {
|
"Vector3Curve": {
|
||||||
"Name": "Vector3Curve",
|
"Name": "Vector3Curve",
|
||||||
"Tags": [],
|
"Tags": [],
|
||||||
@@ -86753,21 +87046,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"UseImprovedModelLod": {
|
|
||||||
"Name": "UseImprovedModelLod",
|
|
||||||
"Scriptability": "None",
|
|
||||||
"DataType": {
|
|
||||||
"Enum": "RolloutState"
|
|
||||||
},
|
|
||||||
"Tags": [
|
|
||||||
"NotScriptable"
|
|
||||||
],
|
|
||||||
"Kind": {
|
|
||||||
"Canonical": {
|
|
||||||
"Serialization": "Serializes"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"UseNewLuauTypeSolver": {
|
"UseNewLuauTypeSolver": {
|
||||||
"Name": "UseNewLuauTypeSolver",
|
"Name": "UseNewLuauTypeSolver",
|
||||||
"Scriptability": "None",
|
"Scriptability": "None",
|
||||||
@@ -86942,6 +87220,9 @@
|
|||||||
"SignalBehavior": {
|
"SignalBehavior": {
|
||||||
"Enum": 0
|
"Enum": 0
|
||||||
},
|
},
|
||||||
|
"SlimHash": {
|
||||||
|
"SharedString": ""
|
||||||
|
},
|
||||||
"SourceAssetId": {
|
"SourceAssetId": {
|
||||||
"Int64": -1
|
"Int64": -1
|
||||||
},
|
},
|
||||||
@@ -86975,9 +87256,6 @@
|
|||||||
"UniqueId": {
|
"UniqueId": {
|
||||||
"UniqueId": "00000000000000000000000000000000"
|
"UniqueId": "00000000000000000000000000000000"
|
||||||
},
|
},
|
||||||
"UseImprovedModelLod": {
|
|
||||||
"Enum": 0
|
|
||||||
},
|
|
||||||
"UseNewLuauTypeSolver": {
|
"UseNewLuauTypeSolver": {
|
||||||
"Enum": 0
|
"Enum": 0
|
||||||
},
|
},
|
||||||
@@ -87103,6 +87381,9 @@
|
|||||||
"Scale": {
|
"Scale": {
|
||||||
"Float32": 1.0
|
"Float32": 1.0
|
||||||
},
|
},
|
||||||
|
"SlimHash": {
|
||||||
|
"SharedString": ""
|
||||||
|
},
|
||||||
"SourceAssetId": {
|
"SourceAssetId": {
|
||||||
"Int64": -1
|
"Int64": -1
|
||||||
},
|
},
|
||||||
@@ -88147,6 +88428,25 @@
|
|||||||
"Timeout": 10
|
"Timeout": 10
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"AnimationNodeType": {
|
||||||
|
"name": "AnimationNodeType",
|
||||||
|
"items": {
|
||||||
|
"AddNode": 1,
|
||||||
|
"Blend1DNode": 3,
|
||||||
|
"Blend2DNode": 4,
|
||||||
|
"BlendNode": 2,
|
||||||
|
"ClipNode": 5,
|
||||||
|
"GraphOutput": 6,
|
||||||
|
"InvalidNode": 0,
|
||||||
|
"MaskNode": 7,
|
||||||
|
"PrioritySelectNode": 8,
|
||||||
|
"RandomSequenceNode": 9,
|
||||||
|
"SelectNode": 10,
|
||||||
|
"SequenceNode": 11,
|
||||||
|
"SpeedNode": 12,
|
||||||
|
"SubtractNode": 13
|
||||||
|
}
|
||||||
|
},
|
||||||
"AnimationPriority": {
|
"AnimationPriority": {
|
||||||
"name": "AnimationPriority",
|
"name": "AnimationPriority",
|
||||||
"items": {
|
"items": {
|
||||||
@@ -88888,6 +89188,13 @@
|
|||||||
"Relevance": 1
|
"Relevance": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"CatalogTimedOptionFilter": {
|
||||||
|
"name": "CatalogTimedOptionFilter",
|
||||||
|
"items": {
|
||||||
|
"All": 1,
|
||||||
|
"TimedOptionOnly": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
"CellBlock": {
|
"CellBlock": {
|
||||||
"name": "CellBlock",
|
"name": "CellBlock",
|
||||||
"items": {
|
"items": {
|
||||||
@@ -89120,6 +89427,12 @@
|
|||||||
"TriggerForIncompleteCompletions": 3
|
"TriggerForIncompleteCompletions": 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"CompressionAlgorithm": {
|
||||||
|
"name": "CompressionAlgorithm",
|
||||||
|
"items": {
|
||||||
|
"Zstd": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
"ComputerCameraMovementMode": {
|
"ComputerCameraMovementMode": {
|
||||||
"name": "ComputerCameraMovementMode",
|
"name": "ComputerCameraMovementMode",
|
||||||
"items": {
|
"items": {
|
||||||
@@ -89403,6 +89716,13 @@
|
|||||||
"Timeout": 1
|
"Timeout": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"DefaultScriptSyncFileType": {
|
||||||
|
"name": "DefaultScriptSyncFileType",
|
||||||
|
"items": {
|
||||||
|
"Lua": 0,
|
||||||
|
"Luau": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
"DevCameraOcclusionMode": {
|
"DevCameraOcclusionMode": {
|
||||||
"name": "DevCameraOcclusionMode",
|
"name": "DevCameraOcclusionMode",
|
||||||
"items": {
|
"items": {
|
||||||
@@ -89482,7 +89802,8 @@
|
|||||||
"DeviceFeatureType": {
|
"DeviceFeatureType": {
|
||||||
"name": "DeviceFeatureType",
|
"name": "DeviceFeatureType",
|
||||||
"items": {
|
"items": {
|
||||||
"DeviceCapture": 0
|
"DeviceCapture": 0,
|
||||||
|
"InExperienceFAE": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DeviceForm": {
|
"DeviceForm": {
|
||||||
@@ -89670,6 +89991,16 @@
|
|||||||
"DefaultScope": 0
|
"DefaultScope": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ExperienceEventStatus": {
|
||||||
|
"name": "ExperienceEventStatus",
|
||||||
|
"items": {
|
||||||
|
"Active": 0,
|
||||||
|
"Cancelled": 1,
|
||||||
|
"Moderated": 2,
|
||||||
|
"Unknown": 4,
|
||||||
|
"Unpublished": 3
|
||||||
|
}
|
||||||
|
},
|
||||||
"ExperienceStateRecordingLoadMode": {
|
"ExperienceStateRecordingLoadMode": {
|
||||||
"name": "ExperienceStateRecordingLoadMode",
|
"name": "ExperienceStateRecordingLoadMode",
|
||||||
"items": {
|
"items": {
|
||||||
@@ -90141,6 +90472,16 @@
|
|||||||
"UINotification": 3
|
"UINotification": 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"HashAlgorithm": {
|
||||||
|
"name": "HashAlgorithm",
|
||||||
|
"items": {
|
||||||
|
"Blake2b": 0,
|
||||||
|
"Blake3": 1,
|
||||||
|
"Md5": 2,
|
||||||
|
"Sha1": 3,
|
||||||
|
"Sha256": 4
|
||||||
|
}
|
||||||
|
},
|
||||||
"HighlightDepthMode": {
|
"HighlightDepthMode": {
|
||||||
"name": "HighlightDepthMode",
|
"name": "HighlightDepthMode",
|
||||||
"items": {
|
"items": {
|
||||||
@@ -90531,14 +90872,14 @@
|
|||||||
"Menu": 319,
|
"Menu": 319,
|
||||||
"Minus": 45,
|
"Minus": 45,
|
||||||
"Mode": 313,
|
"Mode": 313,
|
||||||
"MouseBackButton": 1021,
|
"MouseBackButton": 1029,
|
||||||
"MouseLeftButton": 1018,
|
"MouseLeftButton": 1026,
|
||||||
"MouseMiddleButton": 1020,
|
"MouseMiddleButton": 1028,
|
||||||
"MouseNoButton": 1022,
|
"MouseNoButton": 1030,
|
||||||
"MousePosition": 1025,
|
"MousePosition": 1033,
|
||||||
"MouseRightButton": 1019,
|
"MouseRightButton": 1027,
|
||||||
"MouseX": 1023,
|
"MouseX": 1031,
|
||||||
"MouseY": 1024,
|
"MouseY": 1032,
|
||||||
"N": 110,
|
"N": 110,
|
||||||
"Nine": 57,
|
"Nine": 57,
|
||||||
"NumLock": 300,
|
"NumLock": 300,
|
||||||
@@ -90581,7 +90922,15 @@
|
|||||||
"Tab": 9,
|
"Tab": 9,
|
||||||
"Three": 51,
|
"Three": 51,
|
||||||
"Thumbstick1": 1016,
|
"Thumbstick1": 1016,
|
||||||
|
"Thumbstick1Down": 1019,
|
||||||
|
"Thumbstick1Left": 1020,
|
||||||
|
"Thumbstick1Right": 1021,
|
||||||
|
"Thumbstick1Up": 1018,
|
||||||
"Thumbstick2": 1017,
|
"Thumbstick2": 1017,
|
||||||
|
"Thumbstick2Down": 1023,
|
||||||
|
"Thumbstick2Left": 1024,
|
||||||
|
"Thumbstick2Right": 1025,
|
||||||
|
"Thumbstick2Up": 1022,
|
||||||
"Tilde": 126,
|
"Tilde": 126,
|
||||||
"Two": 50,
|
"Two": 50,
|
||||||
"U": 117,
|
"U": 117,
|
||||||
@@ -91023,6 +91372,7 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"Automatic": 0,
|
"Automatic": 0,
|
||||||
"Disabled": 2,
|
"Disabled": 2,
|
||||||
|
"SLIM": 4,
|
||||||
"StreamingMesh": 1
|
"StreamingMesh": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -91044,6 +91394,30 @@
|
|||||||
"PersistentPerPlayer": 3
|
"PersistentPerPlayer": 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ModerationResultCategory": {
|
||||||
|
"name": "ModerationResultCategory",
|
||||||
|
"items": {
|
||||||
|
"Borderline": 1,
|
||||||
|
"NoViolationDetected": 2,
|
||||||
|
"ViolationDetected": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ModerationResultLabel": {
|
||||||
|
"name": "ModerationResultLabel",
|
||||||
|
"items": {
|
||||||
|
"ChildExploitation": 0,
|
||||||
|
"DiscriminationSlursAndHateSpeech": 4,
|
||||||
|
"IllegalAndRegulatedGoodsAndActivities": 8,
|
||||||
|
"Other": 100,
|
||||||
|
"Profanity": 9,
|
||||||
|
"RealWorldSensitiveEvents": 5,
|
||||||
|
"RomanticAndSexualContent": 7,
|
||||||
|
"SuicideSelfInjuryAndHarmfulBehavior": 1,
|
||||||
|
"TerrorismAndViolentExtremism": 3,
|
||||||
|
"ThreatsBullyingAndHarassment": 2,
|
||||||
|
"ViolentContentAndGore": 6
|
||||||
|
}
|
||||||
|
},
|
||||||
"ModerationStatus": {
|
"ModerationStatus": {
|
||||||
"name": "ModerationStatus",
|
"name": "ModerationStatus",
|
||||||
"items": {
|
"items": {
|
||||||
@@ -91855,6 +92229,14 @@
|
|||||||
"UnderWater": 23
|
"UnderWater": 23
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ReviewableContentState": {
|
||||||
|
"name": "ReviewableContentState",
|
||||||
|
"items": {
|
||||||
|
"Completed": 1,
|
||||||
|
"Failed": 2,
|
||||||
|
"Pending": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
"RibbonTool": {
|
"RibbonTool": {
|
||||||
"name": "RibbonTool",
|
"name": "RibbonTool",
|
||||||
"items": {
|
"items": {
|
||||||
@@ -92084,6 +92466,7 @@
|
|||||||
"AccessOutsideWrite": 2,
|
"AccessOutsideWrite": 2,
|
||||||
"Animation": 15,
|
"Animation": 15,
|
||||||
"AssetRequire": 3,
|
"AssetRequire": 3,
|
||||||
|
"Assistant": 31,
|
||||||
"Audio": 8,
|
"Audio": 8,
|
||||||
"Avatar": 16,
|
"Avatar": 16,
|
||||||
"Basic": 7,
|
"Basic": 7,
|
||||||
@@ -92094,16 +92477,25 @@
|
|||||||
"DataStore": 9,
|
"DataStore": 9,
|
||||||
"Environment": 18,
|
"Environment": 18,
|
||||||
"Input": 17,
|
"Input": 17,
|
||||||
|
"InternalTest": 29,
|
||||||
"LegacySound": 20,
|
"LegacySound": 20,
|
||||||
"LoadString": 4,
|
"LoadString": 4,
|
||||||
|
"LocalUser": 24,
|
||||||
"Network": 10,
|
"Network": 10,
|
||||||
"Physics": 11,
|
"Physics": 11,
|
||||||
"Players": 21,
|
"Players": 21,
|
||||||
|
"Plugin": 23,
|
||||||
|
"PluginOrOpenCloud": 30,
|
||||||
|
"RemoteCommand": 32,
|
||||||
"RemoteEvent": 19,
|
"RemoteEvent": 19,
|
||||||
|
"RobloxEngine": 27,
|
||||||
|
"RobloxScript": 26,
|
||||||
"RunClientScript": 0,
|
"RunClientScript": 0,
|
||||||
"RunServerScript": 1,
|
"RunServerScript": 1,
|
||||||
"ScriptGlobals": 5,
|
"ScriptGlobals": 5,
|
||||||
"UI": 12
|
"UI": 12,
|
||||||
|
"Unassigned": 28,
|
||||||
|
"WritePlayer": 25
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"SelectionBehavior": {
|
"SelectionBehavior": {
|
||||||
@@ -92659,6 +93051,35 @@
|
|||||||
"Voxel": 1
|
"Voxel": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"TelemetryBackend": {
|
||||||
|
"name": "TelemetryBackend",
|
||||||
|
"items": {
|
||||||
|
"Counter": 6,
|
||||||
|
"EphemeralCounter": 4,
|
||||||
|
"EphemeralStat": 5,
|
||||||
|
"EventIngest": 1,
|
||||||
|
"Points": 2,
|
||||||
|
"Stat": 7,
|
||||||
|
"Teletune": 3,
|
||||||
|
"UNSPECIFIED": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TelemetryStandardizedField": {
|
||||||
|
"name": "TelemetryStandardizedField",
|
||||||
|
"items": {
|
||||||
|
"AddArchitectureInfo": 7,
|
||||||
|
"AddCpuInfo": 8,
|
||||||
|
"AddCurrentContextName": 5,
|
||||||
|
"AddDatacenterId": 0,
|
||||||
|
"AddMemoryInfo": 9,
|
||||||
|
"AddOsInfo": 6,
|
||||||
|
"AddPlaceId": 1,
|
||||||
|
"AddPlaceInstanceId": 3,
|
||||||
|
"AddPlaySessionId": 4,
|
||||||
|
"AddSessionInfo": 10,
|
||||||
|
"AddUniverseId": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
"TeleportMethod": {
|
"TeleportMethod": {
|
||||||
"name": "TeleportMethod",
|
"name": "TeleportMethod",
|
||||||
"items": {
|
"items": {
|
||||||
@@ -93098,7 +93519,8 @@
|
|||||||
"CaptureNotInGallery": 3,
|
"CaptureNotInGallery": 3,
|
||||||
"IneligibleCapture": 4,
|
"IneligibleCapture": 4,
|
||||||
"NeedPermission": 1,
|
"NeedPermission": 1,
|
||||||
"Success": 0
|
"Success": 0,
|
||||||
|
"UploadQuotaReached": 5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"UsageContext": {
|
"UsageContext": {
|
||||||
@@ -93430,7 +93852,8 @@
|
|||||||
"name": "WebStreamClientType",
|
"name": "WebStreamClientType",
|
||||||
"items": {
|
"items": {
|
||||||
"RawStream": 1,
|
"RawStream": 1,
|
||||||
"SSE": 0
|
"SSE": 0,
|
||||||
|
"WebSocket": 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"WeldConstraintPreserve": {
|
"WeldConstraintPreserve": {
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ local Packages = Rojo.Packages
|
|||||||
|
|
||||||
local Roact = require(Packages.Roact)
|
local Roact = require(Packages.Roact)
|
||||||
|
|
||||||
local Timer = require(Plugin.Timer)
|
|
||||||
local PatchTree = require(Plugin.PatchTree)
|
|
||||||
local Settings = require(Plugin.Settings)
|
local Settings = require(Plugin.Settings)
|
||||||
local Theme = require(Plugin.App.Theme)
|
local Theme = require(Plugin.App.Theme)
|
||||||
local TextButton = require(Plugin.App.Components.TextButton)
|
local TextButton = require(Plugin.App.Components.TextButton)
|
||||||
@@ -24,7 +22,6 @@ function ConfirmingPage:init()
|
|||||||
self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0))
|
self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0))
|
||||||
|
|
||||||
self:setState({
|
self:setState({
|
||||||
patchTree = nil,
|
|
||||||
showingStringDiff = false,
|
showingStringDiff = false,
|
||||||
oldString = "",
|
oldString = "",
|
||||||
newString = "",
|
newString = "",
|
||||||
@@ -32,28 +29,6 @@ function ConfirmingPage:init()
|
|||||||
oldTable = {},
|
oldTable = {},
|
||||||
newTable = {},
|
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
|
end
|
||||||
|
|
||||||
function ConfirmingPage:render()
|
function ConfirmingPage:render()
|
||||||
@@ -79,7 +54,7 @@ function ConfirmingPage:render()
|
|||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
layoutOrder = 3,
|
layoutOrder = 3,
|
||||||
|
|
||||||
patchTree = self.state.patchTree,
|
patchTree = self.props.patchTree,
|
||||||
|
|
||||||
showStringDiff = function(oldString: string, newString: string)
|
showStringDiff = function(oldString: string, newString: string)
|
||||||
self:setState({
|
self:setState({
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ local Packages = Rojo.Packages
|
|||||||
|
|
||||||
local Roact = require(Packages.Roact)
|
local Roact = require(Packages.Roact)
|
||||||
|
|
||||||
|
local Theme = require(Plugin.App.Theme)
|
||||||
|
|
||||||
local Spinner = require(Plugin.App.Components.Spinner)
|
local Spinner = require(Plugin.App.Components.Spinner)
|
||||||
|
|
||||||
local e = Roact.createElement
|
local e = Roact.createElement
|
||||||
@@ -11,11 +13,35 @@ local e = Roact.createElement
|
|||||||
local ConnectingPage = Roact.Component:extend("ConnectingPage")
|
local ConnectingPage = Roact.Component:extend("ConnectingPage")
|
||||||
|
|
||||||
function ConnectingPage:render()
|
function ConnectingPage:render()
|
||||||
return e(Spinner, {
|
return Theme.with(function(theme)
|
||||||
position = UDim2.new(0.5, 0, 0.5, 0),
|
return e("Frame", {
|
||||||
anchorPoint = Vector2.new(0.5, 0.5),
|
Size = UDim2.new(1, 0, 1, 0),
|
||||||
transparency = self.props.transparency,
|
BackgroundTransparency = 1,
|
||||||
})
|
}, {
|
||||||
|
Spinner = e(Spinner, {
|
||||||
|
position = UDim2.new(0.5, 0, 0.5, 0),
|
||||||
|
anchorPoint = Vector2.new(0.5, 0.5),
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
}),
|
||||||
|
Text = if type(self.props.text) == "string" and #self.props.text > 0
|
||||||
|
then e("TextLabel", {
|
||||||
|
Text = self.props.text,
|
||||||
|
Position = UDim2.new(0.5, 0, 0.5, 30),
|
||||||
|
Size = UDim2.new(1, -40, 0.5, -40),
|
||||||
|
AnchorPoint = Vector2.new(0.5, 0),
|
||||||
|
TextXAlignment = Enum.TextXAlignment.Center,
|
||||||
|
TextYAlignment = Enum.TextYAlignment.Top,
|
||||||
|
RichText = true,
|
||||||
|
FontFace = theme.Font.Thin,
|
||||||
|
TextSize = theme.TextSize.Medium,
|
||||||
|
TextColor3 = theme.SubTextColor,
|
||||||
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
|
TextTransparency = self.props.transparency,
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
})
|
||||||
|
else nil,
|
||||||
|
})
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ConnectingPage
|
return ConnectingPage
|
||||||
|
|||||||
@@ -595,6 +595,12 @@ function App:startSession()
|
|||||||
twoWaySync = Settings:get("twoWaySync"),
|
twoWaySync = Settings:get("twoWaySync"),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
serveSession:setUpdateLoadingTextCallback(function(text: string)
|
||||||
|
self:setState({
|
||||||
|
connectingText = text,
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
self.cleanupPrecommit = serveSession:hookPrecommit(function(patch, instanceMap)
|
self.cleanupPrecommit = serveSession:hookPrecommit(function(patch, instanceMap)
|
||||||
-- Build new tree for patch
|
-- Build new tree for patch
|
||||||
self:setState({
|
self:setState({
|
||||||
@@ -602,46 +608,32 @@ function App:startSession()
|
|||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
self.cleanupPostcommit = serveSession:hookPostcommit(function(patch, instanceMap, unappliedPatch)
|
self.cleanupPostcommit = serveSession:hookPostcommit(function(patch, instanceMap, unappliedPatch)
|
||||||
-- Update tree with unapplied metadata
|
local now = DateTime.now().UnixTimestamp
|
||||||
self:setState(function(prevState)
|
self:setState(function(prevState)
|
||||||
|
local oldPatchData = prevState.patchData
|
||||||
|
local newPatchData = {
|
||||||
|
patch = patch,
|
||||||
|
unapplied = unappliedPatch,
|
||||||
|
timestamp = now,
|
||||||
|
}
|
||||||
|
|
||||||
|
if PatchSet.isEmpty(patch) then
|
||||||
|
-- Keep existing patch info, but use new timestamp
|
||||||
|
newPatchData.patch = oldPatchData.patch
|
||||||
|
newPatchData.unapplied = oldPatchData.unapplied
|
||||||
|
elseif now - oldPatchData.timestamp < 2 then
|
||||||
|
-- Patches that apply in the same second are combined for human clarity
|
||||||
|
newPatchData.patch = PatchSet.assign(PatchSet.newEmpty(), oldPatchData.patch, patch)
|
||||||
|
newPatchData.unapplied = PatchSet.assign(PatchSet.newEmpty(), oldPatchData.unapplied, unappliedPatch)
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
patchTree = PatchTree.updateMetadata(prevState.patchTree, patch, instanceMap, unappliedPatch),
|
patchTree = PatchTree.updateMetadata(prevState.patchTree, patch, instanceMap, unappliedPatch),
|
||||||
|
patchData = newPatchData,
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
serveSession:hookPostcommit(function(patch, _instanceMap, unapplied)
|
|
||||||
local now = DateTime.now().UnixTimestamp
|
|
||||||
local old = self.state.patchData
|
|
||||||
|
|
||||||
if PatchSet.isEmpty(patch) then
|
|
||||||
-- Ignore empty patch, but update timestamp
|
|
||||||
self:setState({
|
|
||||||
patchData = {
|
|
||||||
patch = old.patch,
|
|
||||||
unapplied = old.unapplied,
|
|
||||||
timestamp = now,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
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
|
|
||||||
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)
|
serveSession:onStatusChanged(function(status, details)
|
||||||
if status == ServeSession.Status.Connecting then
|
if status == ServeSession.Status.Connecting then
|
||||||
if self.dismissSyncReminder then
|
if self.dismissSyncReminder then
|
||||||
@@ -773,11 +765,13 @@ function App:startSession()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self:setState({
|
||||||
|
connectingText = "Computing diff view...",
|
||||||
|
})
|
||||||
self:setState({
|
self:setState({
|
||||||
appStatus = AppStatus.Confirming,
|
appStatus = AppStatus.Confirming,
|
||||||
|
patchTree = PatchTree.build(patch, instanceMap, { "Property", "Current", "Incoming" }),
|
||||||
confirmData = {
|
confirmData = {
|
||||||
instanceMap = instanceMap,
|
|
||||||
patch = patch,
|
|
||||||
serverInfo = serverInfo,
|
serverInfo = serverInfo,
|
||||||
},
|
},
|
||||||
toolbarIcon = Assets.Images.PluginButton,
|
toolbarIcon = Assets.Images.PluginButton,
|
||||||
@@ -888,6 +882,7 @@ function App:render()
|
|||||||
|
|
||||||
ConfirmingPage = createPageElement(AppStatus.Confirming, {
|
ConfirmingPage = createPageElement(AppStatus.Confirming, {
|
||||||
confirmData = self.state.confirmData,
|
confirmData = self.state.confirmData,
|
||||||
|
patchTree = self.state.patchTree,
|
||||||
createPopup = not self.state.guiEnabled,
|
createPopup = not self.state.guiEnabled,
|
||||||
|
|
||||||
onAbort = function()
|
onAbort = function()
|
||||||
@@ -901,7 +896,9 @@ function App:render()
|
|||||||
end,
|
end,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Connecting = createPageElement(AppStatus.Connecting),
|
Connecting = createPageElement(AppStatus.Connecting, {
|
||||||
|
text = self.state.connectingText,
|
||||||
|
}),
|
||||||
|
|
||||||
Connected = createPageElement(AppStatus.Connected, {
|
Connected = createPageElement(AppStatus.Connected, {
|
||||||
projectName = self.state.projectName,
|
projectName = self.state.projectName,
|
||||||
|
|||||||
@@ -16,6 +16,14 @@ local Types = require(Plugin.Types)
|
|||||||
local decodeValue = require(Plugin.Reconciler.decodeValue)
|
local decodeValue = require(Plugin.Reconciler.decodeValue)
|
||||||
local getProperty = require(Plugin.Reconciler.getProperty)
|
local getProperty = require(Plugin.Reconciler.getProperty)
|
||||||
|
|
||||||
|
local function yieldIfNeeded(clock)
|
||||||
|
if os.clock() - clock > 1 / 20 then
|
||||||
|
task.wait()
|
||||||
|
return os.clock()
|
||||||
|
end
|
||||||
|
return clock
|
||||||
|
end
|
||||||
|
|
||||||
local function alphabeticalNext(t, state)
|
local function alphabeticalNext(t, state)
|
||||||
-- Equivalent of the next function, but returns the keys in the alphabetic
|
-- 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
|
-- order of node names. We use a temporary ordered key table that is stored in the
|
||||||
@@ -132,7 +140,6 @@ end
|
|||||||
-- props must contain id, and cannot contain children or parentId
|
-- props must contain id, and cannot contain children or parentId
|
||||||
-- other than those three, it can hold anything
|
-- other than those three, it can hold anything
|
||||||
function Tree:addNode(parent, props)
|
function Tree:addNode(parent, props)
|
||||||
Timer.start("Tree:addNode")
|
|
||||||
assert(props.id, "props must contain id")
|
assert(props.id, "props must contain id")
|
||||||
|
|
||||||
parent = parent or "ROOT"
|
parent = parent or "ROOT"
|
||||||
@@ -143,7 +150,6 @@ function Tree:addNode(parent, props)
|
|||||||
for k, v in props do
|
for k, v in props do
|
||||||
node[k] = v
|
node[k] = v
|
||||||
end
|
end
|
||||||
Timer.stop()
|
|
||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -154,25 +160,25 @@ function Tree:addNode(parent, props)
|
|||||||
local parentNode = self:getNode(parent)
|
local parentNode = self:getNode(parent)
|
||||||
if not parentNode then
|
if not parentNode then
|
||||||
Log.warn("Failed to create node since parent doesnt exist: {}, {}", parent, props)
|
Log.warn("Failed to create node since parent doesnt exist: {}, {}", parent, props)
|
||||||
Timer.stop()
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
parentNode.children[node.id] = node
|
parentNode.children[node.id] = node
|
||||||
self.idToNode[node.id] = node
|
self.idToNode[node.id] = node
|
||||||
|
|
||||||
Timer.stop()
|
|
||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Given a list of ancestor ids in descending order, builds the nodes for them
|
-- Given a list of ancestor ids in descending order, builds the nodes for them
|
||||||
-- using the patch and instanceMap info
|
-- using the patch and instanceMap info
|
||||||
function Tree:buildAncestryNodes(previousId: string?, ancestryIds: { string }, patch, instanceMap)
|
function Tree:buildAncestryNodes(previousId: string?, ancestryIds: { string }, patch, instanceMap)
|
||||||
Timer.start("Tree:buildAncestryNodes")
|
local clock = os.clock()
|
||||||
-- Build nodes for ancestry by going up the tree
|
-- Build nodes for ancestry by going up the tree
|
||||||
previousId = previousId or "ROOT"
|
previousId = previousId or "ROOT"
|
||||||
|
|
||||||
for _, ancestorId in ancestryIds do
|
for _, ancestorId in ancestryIds do
|
||||||
|
clock = yieldIfNeeded(clock)
|
||||||
|
|
||||||
local value = instanceMap.fromIds[ancestorId] or patch.added[ancestorId]
|
local value = instanceMap.fromIds[ancestorId] or patch.added[ancestorId]
|
||||||
if not value then
|
if not value then
|
||||||
Log.warn("Failed to find ancestor object for " .. ancestorId)
|
Log.warn("Failed to find ancestor object for " .. ancestorId)
|
||||||
@@ -186,8 +192,6 @@ function Tree:buildAncestryNodes(previousId: string?, ancestryIds: { string }, p
|
|||||||
})
|
})
|
||||||
previousId = ancestorId
|
previousId = ancestorId
|
||||||
end
|
end
|
||||||
|
|
||||||
Timer.stop()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local PatchTree = {}
|
local PatchTree = {}
|
||||||
@@ -196,12 +200,16 @@ local PatchTree = {}
|
|||||||
-- uses changeListHeaders in node.changeList
|
-- uses changeListHeaders in node.changeList
|
||||||
function PatchTree.build(patch, instanceMap, changeListHeaders)
|
function PatchTree.build(patch, instanceMap, changeListHeaders)
|
||||||
Timer.start("PatchTree.build")
|
Timer.start("PatchTree.build")
|
||||||
|
local clock = os.clock()
|
||||||
|
|
||||||
local tree = Tree.new()
|
local tree = Tree.new()
|
||||||
|
|
||||||
local knownAncestors = {}
|
local knownAncestors = {}
|
||||||
|
|
||||||
Timer.start("patch.updated")
|
Timer.start("patch.updated")
|
||||||
for _, change in patch.updated do
|
for _, change in patch.updated do
|
||||||
|
clock = yieldIfNeeded(clock)
|
||||||
|
|
||||||
local instance = instanceMap.fromIds[change.id]
|
local instance = instanceMap.fromIds[change.id]
|
||||||
if not instance then
|
if not instance then
|
||||||
continue
|
continue
|
||||||
@@ -281,6 +289,8 @@ function PatchTree.build(patch, instanceMap, changeListHeaders)
|
|||||||
|
|
||||||
Timer.start("patch.removed")
|
Timer.start("patch.removed")
|
||||||
for _, idOrInstance in patch.removed do
|
for _, idOrInstance in patch.removed do
|
||||||
|
clock = yieldIfNeeded(clock)
|
||||||
|
|
||||||
local instance = if Types.RbxId(idOrInstance) then instanceMap.fromIds[idOrInstance] else idOrInstance
|
local instance = if Types.RbxId(idOrInstance) then instanceMap.fromIds[idOrInstance] else idOrInstance
|
||||||
if not instance then
|
if not instance then
|
||||||
-- If we're viewing a past patch, the instance is already removed
|
-- If we're viewing a past patch, the instance is already removed
|
||||||
@@ -325,6 +335,8 @@ function PatchTree.build(patch, instanceMap, changeListHeaders)
|
|||||||
|
|
||||||
Timer.start("patch.added")
|
Timer.start("patch.added")
|
||||||
for id, change in patch.added do
|
for id, change in patch.added do
|
||||||
|
clock = yieldIfNeeded(clock)
|
||||||
|
|
||||||
-- Gather ancestors from existing DOM or future additions
|
-- Gather ancestors from existing DOM or future additions
|
||||||
local ancestryIds = {}
|
local ancestryIds = {}
|
||||||
local parentId = change.Parent
|
local parentId = change.Parent
|
||||||
|
|||||||
@@ -48,6 +48,12 @@ local function debugPatch(object)
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function attemptReparent(instance, parent)
|
||||||
|
return pcall(function()
|
||||||
|
instance.Parent = parent
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
local ServeSession = {}
|
local ServeSession = {}
|
||||||
ServeSession.__index = ServeSession
|
ServeSession.__index = ServeSession
|
||||||
|
|
||||||
@@ -101,6 +107,7 @@ function ServeSession.new(options)
|
|||||||
__connections = connections,
|
__connections = connections,
|
||||||
__precommitCallbacks = {},
|
__precommitCallbacks = {},
|
||||||
__postcommitCallbacks = {},
|
__postcommitCallbacks = {},
|
||||||
|
__updateLoadingText = function() end,
|
||||||
}
|
}
|
||||||
|
|
||||||
setmetatable(self, ServeSession)
|
setmetatable(self, ServeSession)
|
||||||
@@ -131,6 +138,14 @@ function ServeSession:setConfirmCallback(callback)
|
|||||||
self.__userConfirmCallback = callback
|
self.__userConfirmCallback = callback
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function ServeSession:setUpdateLoadingTextCallback(callback)
|
||||||
|
self.__updateLoadingText = callback
|
||||||
|
end
|
||||||
|
|
||||||
|
function ServeSession:setLoadingText(text: string)
|
||||||
|
self.__updateLoadingText(text)
|
||||||
|
end
|
||||||
|
|
||||||
--[=[
|
--[=[
|
||||||
Hooks a function to run before patch application.
|
Hooks a function to run before patch application.
|
||||||
The provided function is called with the incoming patch and an InstanceMap
|
The provided function is called with the incoming patch and an InstanceMap
|
||||||
@@ -175,11 +190,14 @@ end
|
|||||||
|
|
||||||
function ServeSession:start()
|
function ServeSession:start()
|
||||||
self:__setStatus(Status.Connecting)
|
self:__setStatus(Status.Connecting)
|
||||||
|
self:setLoadingText("Connecting to server...")
|
||||||
|
|
||||||
self.__apiContext
|
self.__apiContext
|
||||||
:connect()
|
:connect()
|
||||||
:andThen(function(serverInfo)
|
:andThen(function(serverInfo)
|
||||||
|
self:setLoadingText("Loading initial data from server...")
|
||||||
return self:__initialSync(serverInfo):andThen(function()
|
return self:__initialSync(serverInfo):andThen(function()
|
||||||
|
self:setLoadingText("Starting sync loop...")
|
||||||
self:__setStatus(Status.Connected, serverInfo.projectName)
|
self:__setStatus(Status.Connected, serverInfo.projectName)
|
||||||
self:__applyGameAndPlaceId(serverInfo)
|
self:__applyGameAndPlaceId(serverInfo)
|
||||||
|
|
||||||
@@ -291,18 +309,52 @@ function ServeSession:__replaceInstances(idList)
|
|||||||
|
|
||||||
for id, replacement in replacements do
|
for id, replacement in replacements do
|
||||||
local oldInstance = self.__instanceMap.fromIds[id]
|
local oldInstance = self.__instanceMap.fromIds[id]
|
||||||
|
if not oldInstance then
|
||||||
|
-- TODO: Why would this happen?
|
||||||
|
Log.warn("Instance {} not found in InstanceMap during sync replacement", id)
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
self.__instanceMap:insert(id, replacement)
|
self.__instanceMap:insert(id, replacement)
|
||||||
Log.trace("Swapping Instance {} out via api/models/ endpoint", id)
|
Log.trace("Swapping Instance {} out via api/models/ endpoint", id)
|
||||||
local oldParent = oldInstance.Parent
|
local oldParent = oldInstance.Parent
|
||||||
for _, child in oldInstance:GetChildren() do
|
for _, child in oldInstance:GetChildren() do
|
||||||
child.Parent = replacement
|
-- Some children cannot be reparented, such as a TouchTransmitter
|
||||||
|
local reparentSuccess, reparentError = attemptReparent(child, replacement)
|
||||||
|
if not reparentSuccess then
|
||||||
|
Log.warn(
|
||||||
|
"Could not reparent child {} of instance {} during sync replacement: {}",
|
||||||
|
child.Name,
|
||||||
|
oldInstance.Name,
|
||||||
|
reparentError
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
replacement.Parent = oldParent
|
|
||||||
-- ChangeHistoryService doesn't like it if an Instance has been
|
-- ChangeHistoryService doesn't like it if an Instance has been
|
||||||
-- Destroyed. So, we have to accept the potential memory hit and
|
-- Destroyed. So, we have to accept the potential memory hit and
|
||||||
-- just set the parent to `nil`.
|
-- just set the parent to `nil`.
|
||||||
oldInstance.Parent = nil
|
local deleteSuccess, deleteError = attemptReparent(oldInstance, nil)
|
||||||
|
local replaceSuccess, replaceError = attemptReparent(replacement, oldParent)
|
||||||
|
|
||||||
|
if not (deleteSuccess and replaceSuccess) then
|
||||||
|
Log.warn(
|
||||||
|
"Could not swap instances {} and {} during sync replacement: {}",
|
||||||
|
oldInstance.Name,
|
||||||
|
replacement.Name,
|
||||||
|
(deleteError or "") .. "\n" .. (replaceError or "")
|
||||||
|
)
|
||||||
|
|
||||||
|
-- We need to revert the failed swap to avoid losing the old instance and children.
|
||||||
|
for _, child in replacement:GetChildren() do
|
||||||
|
attemptReparent(child, oldInstance)
|
||||||
|
end
|
||||||
|
attemptReparent(oldInstance, oldParent)
|
||||||
|
|
||||||
|
-- Our replacement should never have existed in the first place, so we can just destroy it.
|
||||||
|
replacement:Destroy()
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
|
||||||
if selectionMap[oldInstance] then
|
if selectionMap[oldInstance] then
|
||||||
-- This is a bit funky, but it saves the order of Selection
|
-- This is a bit funky, but it saves the order of Selection
|
||||||
@@ -349,18 +401,11 @@ function ServeSession:__applyPatch(patch)
|
|||||||
error(unappliedPatch)
|
error(unappliedPatch)
|
||||||
end
|
end
|
||||||
|
|
||||||
if PatchSet.isEmpty(unappliedPatch) then
|
if Settings:get("enableSyncFallback") and not PatchSet.isEmpty(unappliedPatch) then
|
||||||
if historyRecording then
|
-- Some changes did not apply, let's try replacing them instead
|
||||||
ChangeHistoryService:FinishRecording(historyRecording, Enum.FinishRecordingOperation.Commit)
|
local addedIdList = PatchSet.addedIdList(unappliedPatch)
|
||||||
end
|
local updatedIdList = PatchSet.updatedIdList(unappliedPatch)
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local addedIdList = PatchSet.addedIdList(unappliedPatch)
|
|
||||||
local updatedIdList = PatchSet.updatedIdList(unappliedPatch)
|
|
||||||
|
|
||||||
local actualUnappliedPatches = PatchSet.newEmpty()
|
|
||||||
if Settings:get("enableSyncFallback") then
|
|
||||||
Log.debug("ServeSession:__replaceInstances(unappliedPatch.added)")
|
Log.debug("ServeSession:__replaceInstances(unappliedPatch.added)")
|
||||||
Timer.start("ServeSession:__replaceInstances(unappliedPatch.added)")
|
Timer.start("ServeSession:__replaceInstances(unappliedPatch.added)")
|
||||||
local addSuccess, unappliedAddedRefs = self:__replaceInstances(addedIdList)
|
local addSuccess, unappliedAddedRefs = self:__replaceInstances(addedIdList)
|
||||||
@@ -371,20 +416,18 @@ function ServeSession:__applyPatch(patch)
|
|||||||
local updateSuccess, unappliedUpdateRefs = self:__replaceInstances(updatedIdList)
|
local updateSuccess, unappliedUpdateRefs = self:__replaceInstances(updatedIdList)
|
||||||
Timer.stop()
|
Timer.stop()
|
||||||
|
|
||||||
|
-- Update the unapplied patch to reflect which Instances were replaced successfully
|
||||||
if addSuccess then
|
if addSuccess then
|
||||||
table.clear(unappliedPatch.added)
|
table.clear(unappliedPatch.added)
|
||||||
PatchSet.assign(actualUnappliedPatches, unappliedAddedRefs)
|
PatchSet.assign(unappliedPatch, unappliedAddedRefs)
|
||||||
end
|
end
|
||||||
if updateSuccess then
|
if updateSuccess then
|
||||||
table.clear(unappliedPatch.updated)
|
table.clear(unappliedPatch.updated)
|
||||||
PatchSet.assign(actualUnappliedPatches, unappliedUpdateRefs)
|
PatchSet.assign(unappliedPatch, unappliedUpdateRefs)
|
||||||
end
|
end
|
||||||
else
|
|
||||||
Log.debug("Skipping ServeSession:__replaceInstances because of setting")
|
|
||||||
end
|
end
|
||||||
PatchSet.assign(actualUnappliedPatches, unappliedPatch)
|
|
||||||
|
|
||||||
if not PatchSet.isEmpty(actualUnappliedPatches) then
|
if not PatchSet.isEmpty(unappliedPatch) then
|
||||||
Log.debug(
|
Log.debug(
|
||||||
"Could not apply all changes requested by the Rojo server:\n{}",
|
"Could not apply all changes requested by the Rojo server:\n{}",
|
||||||
PatchSet.humanSummary(self.__instanceMap, unappliedPatch)
|
PatchSet.humanSummary(self.__instanceMap, unappliedPatch)
|
||||||
@@ -396,7 +439,7 @@ function ServeSession:__applyPatch(patch)
|
|||||||
-- guaranteed to be called after the commit
|
-- guaranteed to be called after the commit
|
||||||
for _, callback in self.__postcommitCallbacks do
|
for _, callback in self.__postcommitCallbacks do
|
||||||
task.spawn(function()
|
task.spawn(function()
|
||||||
local success, err = pcall(callback, patch, self.__instanceMap, actualUnappliedPatches)
|
local success, err = pcall(callback, patch, self.__instanceMap, unappliedPatch)
|
||||||
if not success then
|
if not success then
|
||||||
Log.warn("Postcommit hook errored: {}", err)
|
Log.warn("Postcommit hook errored: {}", err)
|
||||||
end
|
end
|
||||||
@@ -418,11 +461,13 @@ function ServeSession:__initialSync(serverInfo)
|
|||||||
-- For any instances that line up with the Rojo server's view, start
|
-- For any instances that line up with the Rojo server's view, start
|
||||||
-- tracking them in the reconciler.
|
-- tracking them in the reconciler.
|
||||||
Log.trace("Matching existing Roblox instances to Rojo IDs")
|
Log.trace("Matching existing Roblox instances to Rojo IDs")
|
||||||
|
self:setLoadingText("Hydrating instance map...")
|
||||||
self.__reconciler:hydrate(readResponseBody.instances, serverInfo.rootInstanceId, game)
|
self.__reconciler:hydrate(readResponseBody.instances, serverInfo.rootInstanceId, game)
|
||||||
|
|
||||||
-- Calculate the initial patch to apply to the DataModel to catch us
|
-- Calculate the initial patch to apply to the DataModel to catch us
|
||||||
-- up to what Rojo thinks the place should look like.
|
-- up to what Rojo thinks the place should look like.
|
||||||
Log.trace("Computing changes that plugin needs to make to catch up to server...")
|
Log.trace("Computing changes that plugin needs to make to catch up to server...")
|
||||||
|
self:setLoadingText("Finding differences between server and Studio...")
|
||||||
local success, catchUpPatch =
|
local success, catchUpPatch =
|
||||||
self.__reconciler:diff(readResponseBody.instances, serverInfo.rootInstanceId, game)
|
self.__reconciler:diff(readResponseBody.instances, serverInfo.rootInstanceId, game)
|
||||||
|
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ impl Serialize for Glob {
|
|||||||
|
|
||||||
impl<'de> Deserialize<'de> for Glob {
|
impl<'de> Deserialize<'de> for Glob {
|
||||||
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
let glob = <&str as Deserialize>::deserialize(deserializer)?;
|
let glob = String::deserialize(deserializer)?;
|
||||||
|
|
||||||
Glob::new(glob).map_err(D::Error::custom)
|
Glob::new(&glob).map_err(D::Error::custom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
313
src/json.rs
Normal file
313
src/json.rs
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
//! Utilities for parsing JSON with comments (JSONC) and deserializing to Rust types.
|
||||||
|
//!
|
||||||
|
//! This module provides convenient wrappers around `jsonc_parser` and `serde_json`
|
||||||
|
//! to reduce boilerplate and improve ergonomics when working with JSONC files.
|
||||||
|
|
||||||
|
use anyhow::Context as _;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
|
/// Parse JSONC text into a `serde_json::Value`.
|
||||||
|
///
|
||||||
|
/// This handles the common pattern of calling `jsonc_parser::parse_to_serde_value`
|
||||||
|
/// and unwrapping the `Option` with a clear error message.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if:
|
||||||
|
/// - The text is not valid JSONC
|
||||||
|
/// - The text contains no JSON value
|
||||||
|
pub fn parse_value(text: &str) -> anyhow::Result<serde_json::Value> {
|
||||||
|
jsonc_parser::parse_to_serde_value(text, &Default::default())
|
||||||
|
.context("Failed to parse JSONC")?
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("File contains no JSON value"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse JSONC text into a `serde_json::Value` with a custom context message.
|
||||||
|
///
|
||||||
|
/// This is useful when you want to provide a specific error message that includes
|
||||||
|
/// additional information like the file path.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if:
|
||||||
|
/// - The text is not valid JSONC
|
||||||
|
/// - The text contains no JSON value
|
||||||
|
pub fn parse_value_with_context(
|
||||||
|
text: &str,
|
||||||
|
context: impl Fn() -> String,
|
||||||
|
) -> anyhow::Result<serde_json::Value> {
|
||||||
|
jsonc_parser::parse_to_serde_value(text, &Default::default())
|
||||||
|
.with_context(|| format!("{}: JSONC parse error", context()))?
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("{}: File contains no JSON value", context()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse JSONC text and deserialize it into a specific type.
|
||||||
|
///
|
||||||
|
/// This combines parsing JSONC and deserializing into a single operation,
|
||||||
|
/// eliminating the need to manually chain `parse_to_serde_value` and `from_value`.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if:
|
||||||
|
/// - The text is not valid JSONC
|
||||||
|
/// - The text contains no JSON value
|
||||||
|
/// - The value cannot be deserialized into type `T`
|
||||||
|
pub fn from_str<T: DeserializeOwned>(text: &str) -> anyhow::Result<T> {
|
||||||
|
let value = parse_value(text)?;
|
||||||
|
serde_json::from_value(value).context("Failed to deserialize JSON")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse JSONC text and deserialize it into a specific type with a custom context message.
|
||||||
|
///
|
||||||
|
/// This is useful when you want to provide a specific error message that includes
|
||||||
|
/// additional information like the file path.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if:
|
||||||
|
/// - The text is not valid JSONC
|
||||||
|
/// - The text contains no JSON value
|
||||||
|
/// - The value cannot be deserialized into type `T`
|
||||||
|
pub fn from_str_with_context<T: DeserializeOwned>(
|
||||||
|
text: &str,
|
||||||
|
context: impl Fn() -> String,
|
||||||
|
) -> anyhow::Result<T> {
|
||||||
|
let value = parse_value_with_context(text, &context)?;
|
||||||
|
serde_json::from_value(value).with_context(|| format!("{}: Invalid JSON structure", context()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse JSONC bytes into a `serde_json::Value` with a custom context message.
|
||||||
|
///
|
||||||
|
/// This handles UTF-8 conversion and JSONC parsing in one step.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if:
|
||||||
|
/// - The bytes are not valid UTF-8
|
||||||
|
/// - The text is not valid JSONC
|
||||||
|
/// - The text contains no JSON value
|
||||||
|
pub fn parse_value_from_slice_with_context(
|
||||||
|
slice: &[u8],
|
||||||
|
context: impl Fn() -> String,
|
||||||
|
) -> anyhow::Result<serde_json::Value> {
|
||||||
|
let text = std::str::from_utf8(slice)
|
||||||
|
.with_context(|| format!("{}: File is not valid UTF-8", context()))?;
|
||||||
|
parse_value_with_context(text, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse JSONC bytes and deserialize it into a specific type.
|
||||||
|
///
|
||||||
|
/// This handles UTF-8 conversion, JSONC parsing, and deserialization in one step.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if:
|
||||||
|
/// - The bytes are not valid UTF-8
|
||||||
|
/// - The text is not valid JSONC
|
||||||
|
/// - The text contains no JSON value
|
||||||
|
/// - The value cannot be deserialized into type `T`
|
||||||
|
pub fn from_slice<T: DeserializeOwned>(slice: &[u8]) -> anyhow::Result<T> {
|
||||||
|
let text = std::str::from_utf8(slice).context("File is not valid UTF-8")?;
|
||||||
|
from_str(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse JSONC bytes and deserialize it into a specific type with a custom context message.
|
||||||
|
///
|
||||||
|
/// This handles UTF-8 conversion, JSONC parsing, and deserialization in one step.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if:
|
||||||
|
/// - The bytes are not valid UTF-8
|
||||||
|
/// - The text is not valid JSONC
|
||||||
|
/// - The text contains no JSON value
|
||||||
|
/// - The value cannot be deserialized into type `T`
|
||||||
|
pub fn from_slice_with_context<T: DeserializeOwned>(
|
||||||
|
slice: &[u8],
|
||||||
|
context: impl Fn() -> String,
|
||||||
|
) -> anyhow::Result<T> {
|
||||||
|
let text = std::str::from_utf8(slice)
|
||||||
|
.with_context(|| format!("{}: File is not valid UTF-8", context()))?;
|
||||||
|
from_str_with_context(text, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_value() {
|
||||||
|
let value = parse_value(r#"{"foo": "bar"}"#).unwrap();
|
||||||
|
assert_eq!(value["foo"], "bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_value_with_comments() {
|
||||||
|
let value = parse_value(
|
||||||
|
r#"{
|
||||||
|
// This is a comment
|
||||||
|
"foo": "bar" // Inline comment
|
||||||
|
}"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(value["foo"], "bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_value_with_trailing_comma() {
|
||||||
|
let value = parse_value(
|
||||||
|
r#"{
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": 123,
|
||||||
|
}"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(value["foo"], "bar");
|
||||||
|
assert_eq!(value["baz"], 123);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_value_empty() {
|
||||||
|
let err = parse_value("").unwrap_err();
|
||||||
|
assert!(err.to_string().contains("no JSON value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_value_invalid() {
|
||||||
|
let err = parse_value("{invalid}").unwrap_err();
|
||||||
|
assert!(err.to_string().contains("parse"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_value_with_context() {
|
||||||
|
let err = parse_value_with_context("{invalid}", || "test.json".to_string()).unwrap_err();
|
||||||
|
assert!(err.to_string().contains("test.json"));
|
||||||
|
assert!(err.to_string().contains("parse"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
|
struct TestStruct {
|
||||||
|
foo: String,
|
||||||
|
bar: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_str() {
|
||||||
|
let result: TestStruct = from_str(r#"{"foo": "hello", "bar": 42}"#).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
TestStruct {
|
||||||
|
foo: "hello".to_string(),
|
||||||
|
bar: 42
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_str_with_comments() {
|
||||||
|
let result: TestStruct = from_str(
|
||||||
|
r#"{
|
||||||
|
// Comment
|
||||||
|
"foo": "hello",
|
||||||
|
"bar": 42, // Trailing comma is fine
|
||||||
|
}"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
TestStruct {
|
||||||
|
foo: "hello".to_string(),
|
||||||
|
bar: 42
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_str_invalid_type() {
|
||||||
|
let err = from_str::<TestStruct>(r#"{"foo": "hello"}"#).unwrap_err();
|
||||||
|
assert!(err.to_string().contains("deserialize"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_str_with_context() {
|
||||||
|
let err = from_str_with_context::<TestStruct>(r#"{"foo": "hello"}"#, || {
|
||||||
|
"config.json".to_string()
|
||||||
|
})
|
||||||
|
.unwrap_err();
|
||||||
|
assert!(err.to_string().contains("config.json"));
|
||||||
|
assert!(err.to_string().contains("Invalid JSON structure"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_value_from_slice_with_context() {
|
||||||
|
let err = parse_value_from_slice_with_context(b"{invalid}", || "test.json".to_string())
|
||||||
|
.unwrap_err();
|
||||||
|
assert!(err.to_string().contains("test.json"));
|
||||||
|
assert!(err.to_string().contains("parse"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_value_from_slice_with_context_invalid_utf8() {
|
||||||
|
let err = parse_value_from_slice_with_context(&[0xFF, 0xFF], || "test.json".to_string())
|
||||||
|
.unwrap_err();
|
||||||
|
assert!(err.to_string().contains("test.json"));
|
||||||
|
assert!(err.to_string().contains("UTF-8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_slice() {
|
||||||
|
let result: TestStruct = from_slice(br#"{"foo": "hello", "bar": 42}"#).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
TestStruct {
|
||||||
|
foo: "hello".to_string(),
|
||||||
|
bar: 42
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_slice_with_comments() {
|
||||||
|
let result: TestStruct = from_slice(
|
||||||
|
br#"{
|
||||||
|
// Comment
|
||||||
|
"foo": "hello",
|
||||||
|
"bar": 42, // Trailing comma is fine
|
||||||
|
}"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
TestStruct {
|
||||||
|
foo: "hello".to_string(),
|
||||||
|
bar: 42
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_slice_invalid_utf8() {
|
||||||
|
let err = from_slice::<TestStruct>(&[0xFF, 0xFF]).unwrap_err();
|
||||||
|
assert!(err.to_string().contains("UTF-8"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_slice_with_context() {
|
||||||
|
let err = from_slice_with_context::<TestStruct>(br#"{"foo": "hello"}"#, || {
|
||||||
|
"config.json".to_string()
|
||||||
|
})
|
||||||
|
.unwrap_err();
|
||||||
|
assert!(err.to_string().contains("config.json"));
|
||||||
|
assert!(err.to_string().contains("Invalid JSON structure"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_from_slice_with_context_invalid_utf8() {
|
||||||
|
let err =
|
||||||
|
from_slice_with_context::<TestStruct>(&[0xFF, 0xFF], || "config.json".to_string())
|
||||||
|
.unwrap_err();
|
||||||
|
assert!(err.to_string().contains("config.json"));
|
||||||
|
assert!(err.to_string().contains("UTF-8"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ mod tree_view;
|
|||||||
mod auth_cookie;
|
mod auth_cookie;
|
||||||
mod change_processor;
|
mod change_processor;
|
||||||
mod glob;
|
mod glob;
|
||||||
|
mod json;
|
||||||
mod lua_ast;
|
mod lua_ast;
|
||||||
mod message_queue;
|
mod message_queue;
|
||||||
mod multimap;
|
mod multimap;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use rbx_dom_weak::{Ustr, UstrMap};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{glob::Glob, resolution::UnresolvedValue, snapshot::SyncRule};
|
use crate::{glob::Glob, json, resolution::UnresolvedValue, snapshot::SyncRule};
|
||||||
|
|
||||||
static PROJECT_FILENAME: &str = "default.project.json";
|
static PROJECT_FILENAME: &str = "default.project.json";
|
||||||
|
|
||||||
@@ -214,8 +214,11 @@ impl Project {
|
|||||||
project_file_location: PathBuf,
|
project_file_location: PathBuf,
|
||||||
fallback_name: Option<&str>,
|
fallback_name: Option<&str>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let mut project: Self = serde_json::from_slice(contents).map_err(|source| Error::Json {
|
let mut project: Self = json::from_slice(contents).map_err(|e| Error::Json {
|
||||||
source,
|
source: serde_json::Error::io(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::InvalidData,
|
||||||
|
e.to_string(),
|
||||||
|
)),
|
||||||
path: project_file_location.clone(),
|
path: project_file_location.clone(),
|
||||||
})?;
|
})?;
|
||||||
project.file_location = project_file_location;
|
project.file_location = project_file_location;
|
||||||
@@ -399,13 +402,13 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn path_node_required() {
|
fn path_node_required() {
|
||||||
let path_node: PathNode = serde_json::from_str(r#""src""#).unwrap();
|
let path_node: PathNode = json::from_str(r#""src""#).unwrap();
|
||||||
assert_eq!(path_node, PathNode::Required(PathBuf::from("src")));
|
assert_eq!(path_node, PathNode::Required(PathBuf::from("src")));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn path_node_optional() {
|
fn path_node_optional() {
|
||||||
let path_node: PathNode = serde_json::from_str(r#"{ "optional": "src" }"#).unwrap();
|
let path_node: PathNode = json::from_str(r#"{ "optional": "src" }"#).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
path_node,
|
path_node,
|
||||||
PathNode::Optional(OptionalPathNode::new(PathBuf::from("src")))
|
PathNode::Optional(OptionalPathNode::new(PathBuf::from("src")))
|
||||||
@@ -414,7 +417,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn project_node_required() {
|
fn project_node_required() {
|
||||||
let project_node: ProjectNode = serde_json::from_str(
|
let project_node: ProjectNode = json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
"$path": "src"
|
"$path": "src"
|
||||||
}"#,
|
}"#,
|
||||||
@@ -429,7 +432,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn project_node_optional() {
|
fn project_node_optional() {
|
||||||
let project_node: ProjectNode = serde_json::from_str(
|
let project_node: ProjectNode = json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
"$path": { "optional": "src" }
|
"$path": { "optional": "src" }
|
||||||
}"#,
|
}"#,
|
||||||
@@ -446,7 +449,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn project_node_none() {
|
fn project_node_none() {
|
||||||
let project_node: ProjectNode = serde_json::from_str(
|
let project_node: ProjectNode = json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
"$className": "Folder"
|
"$className": "Folder"
|
||||||
}"#,
|
}"#,
|
||||||
@@ -458,7 +461,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn project_node_optional_serialize_absolute() {
|
fn project_node_optional_serialize_absolute() {
|
||||||
let project_node: ProjectNode = serde_json::from_str(
|
let project_node: ProjectNode = json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
"$path": { "optional": "..\\src" }
|
"$path": { "optional": "..\\src" }
|
||||||
}"#,
|
}"#,
|
||||||
@@ -471,7 +474,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn project_node_optional_serialize_absolute_no_change() {
|
fn project_node_optional_serialize_absolute_no_change() {
|
||||||
let project_node: ProjectNode = serde_json::from_str(
|
let project_node: ProjectNode = json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
"$path": { "optional": "../src" }
|
"$path": { "optional": "../src" }
|
||||||
}"#,
|
}"#,
|
||||||
@@ -484,7 +487,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn project_node_optional_serialize_optional() {
|
fn project_node_optional_serialize_optional() {
|
||||||
let project_node: ProjectNode = serde_json::from_str(
|
let project_node: ProjectNode = json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
"$path": "..\\src"
|
"$path": "..\\src"
|
||||||
}"#,
|
}"#,
|
||||||
@@ -494,4 +497,57 @@ mod test {
|
|||||||
let serialized = serde_json::to_string(&project_node).unwrap();
|
let serialized = serde_json::to_string(&project_node).unwrap();
|
||||||
assert_eq!(serialized, r#"{"$path":"../src"}"#);
|
assert_eq!(serialized, r#"{"$path":"../src"}"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn project_with_jsonc_features() {
|
||||||
|
// Test that JSONC features (comments and trailing commas) are properly handled
|
||||||
|
let project_json = r#"{
|
||||||
|
// This is a single-line comment
|
||||||
|
"name": "TestProject",
|
||||||
|
/* This is a
|
||||||
|
multi-line comment */
|
||||||
|
"tree": {
|
||||||
|
"$path": "src", // Comment after value
|
||||||
|
},
|
||||||
|
"servePort": 34567,
|
||||||
|
"emitLegacyScripts": false,
|
||||||
|
// Test glob parsing with comments
|
||||||
|
"globIgnorePaths": [
|
||||||
|
"**/*.spec.lua", // Ignore test files
|
||||||
|
"**/*.test.lua",
|
||||||
|
],
|
||||||
|
"syncRules": [
|
||||||
|
{
|
||||||
|
"pattern": "*.data.json",
|
||||||
|
"use": "json", // Trailing comma in object
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"pattern": "*.module.lua",
|
||||||
|
"use": "moduleScript",
|
||||||
|
}, // Trailing comma in array
|
||||||
|
], // Another trailing comma
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
let project = Project::load_from_slice(
|
||||||
|
project_json.as_bytes(),
|
||||||
|
PathBuf::from("/test/default.project.json"),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.expect("Failed to parse project with JSONC features");
|
||||||
|
|
||||||
|
// Verify the parsed values
|
||||||
|
assert_eq!(project.name, Some("TestProject".to_string()));
|
||||||
|
assert_eq!(project.serve_port, Some(34567));
|
||||||
|
assert_eq!(project.emit_legacy_scripts, Some(false));
|
||||||
|
|
||||||
|
// Verify glob_ignore_paths were parsed correctly
|
||||||
|
assert_eq!(project.glob_ignore_paths.len(), 2);
|
||||||
|
assert!(project.glob_ignore_paths[0].is_match("test/foo.spec.lua"));
|
||||||
|
assert!(project.glob_ignore_paths[1].is_match("test/bar.test.lua"));
|
||||||
|
|
||||||
|
// Verify sync_rules were parsed correctly
|
||||||
|
assert_eq!(project.sync_rules.len(), 2);
|
||||||
|
assert!(project.sync_rules[0].include.is_match("data.data.json"));
|
||||||
|
assert!(project.sync_rules[1].include.is_match("init.module.lua"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,14 +248,15 @@ fn nonexhaustive_list(values: &[&str]) -> String {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::json;
|
||||||
|
|
||||||
fn resolve(class: &str, prop: &str, json_value: &str) -> Variant {
|
fn resolve(class: &str, prop: &str, json_value: &str) -> Variant {
|
||||||
let unresolved: UnresolvedValue = serde_json::from_str(json_value).unwrap();
|
let unresolved: UnresolvedValue = json::from_str(json_value).unwrap();
|
||||||
unresolved.resolve(class, prop).unwrap()
|
unresolved.resolve(class, prop).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_unambiguous(json_value: &str) -> Variant {
|
fn resolve_unambiguous(json_value: &str) -> Variant {
|
||||||
let unresolved: UnresolvedValue = serde_json::from_str(json_value).unwrap();
|
let unresolved: UnresolvedValue = json::from_str(json_value).unwrap();
|
||||||
unresolved.resolve_unambiguous().unwrap()
|
unresolved.resolve_unambiguous().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use memofs::{IoResultExt, Vfs};
|
use memofs::{IoResultExt, Vfs};
|
||||||
use rbx_dom_weak::ustr;
|
use rbx_dom_weak::ustr;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
json,
|
||||||
lua_ast::{Expression, Statement},
|
lua_ast::{Expression, Statement},
|
||||||
snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot},
|
snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot},
|
||||||
};
|
};
|
||||||
@@ -19,8 +19,9 @@ pub fn snapshot_json(
|
|||||||
) -> anyhow::Result<Option<InstanceSnapshot>> {
|
) -> anyhow::Result<Option<InstanceSnapshot>> {
|
||||||
let contents = vfs.read(path)?;
|
let contents = vfs.read(path)?;
|
||||||
|
|
||||||
let value: serde_json::Value = serde_json::from_slice(&contents)
|
let value = json::parse_value_from_slice_with_context(&contents, || {
|
||||||
.with_context(|| format!("File contains malformed JSON: {}", path.display()))?;
|
format!("File contains malformed JSON: {}", path.display())
|
||||||
|
})?;
|
||||||
|
|
||||||
let as_lua = json_to_lua(value).to_string();
|
let as_lua = json_to_lua(value).to_string();
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use rbx_dom_weak::{
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
json,
|
||||||
resolution::UnresolvedValue,
|
resolution::UnresolvedValue,
|
||||||
snapshot::{InstanceContext, InstanceSnapshot},
|
snapshot::{InstanceContext, InstanceSnapshot},
|
||||||
RojoRef,
|
RojoRef,
|
||||||
@@ -28,8 +29,9 @@ pub fn snapshot_json_model(
|
|||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut instance: JsonModel = serde_json::from_str(contents_str)
|
let mut instance: JsonModel = json::from_str_with_context(contents_str, || {
|
||||||
.with_context(|| format!("File is not a valid JSON model: {}", path.display()))?;
|
format!("File is not a valid JSON model: {}", path.display())
|
||||||
|
})?;
|
||||||
|
|
||||||
if let Some(top_level_name) = &instance.name {
|
if let Some(top_level_name) = &instance.name {
|
||||||
let new_name = format!("{}.model.json", top_level_name);
|
let new_name = format!("{}.model.json", top_level_name);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use anyhow::{format_err, Context};
|
|||||||
use rbx_dom_weak::{types::Attributes, Ustr, UstrMap};
|
use rbx_dom_weak::{types::Attributes, Ustr, UstrMap};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{resolution::UnresolvedValue, snapshot::InstanceSnapshot, RojoRef};
|
use crate::{json, resolution::UnresolvedValue, snapshot::InstanceSnapshot, RojoRef};
|
||||||
|
|
||||||
/// Represents metadata in a sibling file with the same basename.
|
/// Represents metadata in a sibling file with the same basename.
|
||||||
///
|
///
|
||||||
@@ -34,7 +34,7 @@ pub struct AdjacentMetadata {
|
|||||||
|
|
||||||
impl AdjacentMetadata {
|
impl AdjacentMetadata {
|
||||||
pub fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result<Self> {
|
pub fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result<Self> {
|
||||||
let mut meta: Self = serde_json::from_slice(slice).with_context(|| {
|
let mut meta: Self = json::from_slice_with_context(slice, || {
|
||||||
format!(
|
format!(
|
||||||
"File contained malformed .meta.json data: {}",
|
"File contained malformed .meta.json data: {}",
|
||||||
path.display()
|
path.display()
|
||||||
@@ -131,7 +131,7 @@ pub struct DirectoryMetadata {
|
|||||||
|
|
||||||
impl DirectoryMetadata {
|
impl DirectoryMetadata {
|
||||||
pub fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result<Self> {
|
pub fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result<Self> {
|
||||||
let mut meta: Self = serde_json::from_slice(slice).with_context(|| {
|
let mut meta: Self = json::from_slice_with_context(slice, || {
|
||||||
format!(
|
format!(
|
||||||
"File contained malformed init.meta.json data: {}",
|
"File contained malformed init.meta.json data: {}",
|
||||||
path.display()
|
path.display()
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ use rbx_dom_weak::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
json,
|
||||||
serve_session::ServeSession,
|
serve_session::ServeSession,
|
||||||
snapshot::{InstanceWithMeta, PatchSet, PatchUpdate},
|
snapshot::{InstanceWithMeta, PatchSet, PatchUpdate},
|
||||||
web::{
|
web::{
|
||||||
@@ -139,7 +140,7 @@ impl ApiService {
|
|||||||
|
|
||||||
let body = body::to_bytes(request.into_body()).await.unwrap();
|
let body = body::to_bytes(request.into_body()).await.unwrap();
|
||||||
|
|
||||||
let request: WriteRequest = match serde_json::from_slice(&body) {
|
let request: WriteRequest = match json::from_slice(&body) {
|
||||||
Ok(request) => request,
|
Ok(request) => request,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return json(
|
return json(
|
||||||
|
|||||||
@@ -157,14 +157,20 @@ impl TestServeSession {
|
|||||||
let url = format!("http://localhost:{}/api/rojo", self.port);
|
let url = format!("http://localhost:{}/api/rojo", self.port);
|
||||||
let body = reqwest::blocking::get(url)?.text()?;
|
let body = reqwest::blocking::get(url)?.text()?;
|
||||||
|
|
||||||
Ok(serde_json::from_str(&body).expect("Server returned malformed response"))
|
let value = jsonc_parser::parse_to_serde_value(&body, &Default::default())
|
||||||
|
.expect("Failed to parse JSON")
|
||||||
|
.expect("No JSON value");
|
||||||
|
Ok(serde_json::from_value(value).expect("Server returned malformed response"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_api_read(&self, id: Ref) -> Result<ReadResponse<'_>, reqwest::Error> {
|
pub fn get_api_read(&self, id: Ref) -> Result<ReadResponse<'_>, reqwest::Error> {
|
||||||
let url = format!("http://localhost:{}/api/read/{}", self.port, id);
|
let url = format!("http://localhost:{}/api/read/{}", self.port, id);
|
||||||
let body = reqwest::blocking::get(url)?.text()?;
|
let body = reqwest::blocking::get(url)?.text()?;
|
||||||
|
|
||||||
Ok(serde_json::from_str(&body).expect("Server returned malformed response"))
|
let value = jsonc_parser::parse_to_serde_value(&body, &Default::default())
|
||||||
|
.expect("Failed to parse JSON")
|
||||||
|
.expect("No JSON value");
|
||||||
|
Ok(serde_json::from_value(value).expect("Server returned malformed response"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_api_subscribe(
|
pub fn get_api_subscribe(
|
||||||
|
|||||||
Reference in New Issue
Block a user