Compare commits

...

51 Commits

Author SHA1 Message Date
Lucien Greathouse
dff2df4c79 Update Changelog 2020-10-28 14:53:42 -07:00
Lucien Greathouse
7fe99a2483 Update dependencies 2020-10-28 14:51:59 -07:00
Lucien Greathouse
5d7640f6fa Update to latest rbx-dom from dom-v1 branch 2020-10-28 14:46:12 -07:00
Lucien Greathouse
937c3713dd Update plugin version. Release 0.5.4 (take 3) 2020-02-27 10:16:31 -08:00
Lucien Greathouse
f3ba1b1f16 Turn off rustfmt/clippy for 0.5.x branch 2020-02-26 18:15:02 -08:00
Lucien Greathouse
1c9905f6e2 Port GitHub workflows from master branch 2020-02-26 18:04:17 -08:00
Lucien Greathouse
e5d16e768e Release 0.5.4 2020-02-26 18:02:49 -08:00
Lucien Greathouse
61dd407126 Merge changelog from master 2020-02-26 17:55:52 -08:00
Lucien Greathouse
a34eeb163a Upgrade rbx-dom 2019-10-17 17:33:07 -07:00
Lucien Greathouse
1a78e9178a Release 0.5.3 2019-10-15 18:16:21 -07:00
Lucien Greathouse
1659cf7a01 Plugin: Upgrade to latest rbx_dom_lua 2019-10-15 18:05:43 -07:00
Lucien Greathouse
78d97e162c Release v0.5.2 2019-10-14 17:33:43 -07:00
Lucien Greathouse
5d0aa1193f Fix LocalizationTable output order by switching to a BTreeMap.
ACTUALLY closes #173.
2019-10-14 17:29:34 -07:00
Lucien Greathouse
126040a87b Add build tests for init.meta.json 2019-10-12 23:59:54 -07:00
Lucien Greathouse
2c408f4047 Fix errors in 'Sync Details' page 2019-10-08 16:17:13 -07:00
Lucien Greathouse
b53cda787a Add end-to-end build test for Script.Disabled via .meta.json 2019-10-08 16:09:27 -07:00
Lucien Greathouse
7b4455ed51 Release v0.5.1 2019-10-04 12:51:14 -07:00
Lucien Greathouse
5b57025b0b plugin: Only move message cursor in response to retrieveMessages 2019-10-04 11:13:10 -07:00
Lucien Greathouse
ece454e6dd Update dependencies 2019-10-04 10:54:53 -07:00
boyned//Kampfkarren
afa480b07d Fix broken link to sync details (#248) 2019-09-22 17:38:40 -07:00
Lucien Greathouse
c9b695d533 Fix guide to point to release versions instead of alphas 2019-09-20 11:06:01 -07:00
Lucien Greathouse
71c77a09a6 Update docs link to rojo.space 2019-09-19 14:02:26 -07:00
Lucien Greathouse
d309a1359c Update changelog 2019-09-13 17:16:05 -07:00
Lucien Greathouse
b0bb486d9a Improve diagnostics for failed instance creation 2019-09-13 16:00:08 -07:00
Lucien Greathouse
2c7c3348cf Add help page to direct people to Discord, GitHub, and Twitter 2019-09-11 11:36:02 -07:00
Lucien Greathouse
4caac5e6cb Update docs home for 0.5.x 2019-08-27 14:37:26 -07:00
Lucien Greathouse
009a99a8eb Fix date on Changelog (oops) 2019-08-27 14:26:00 -07:00
Lucien Greathouse
91caa67e04 Release 0.5.0 stable (#234)
* This should be everything?

* Add contributing guide
2019-08-27 14:14:48 -07:00
Lucien Greathouse
53793f7dd2 Update and improve reference documentation 2019-08-26 17:23:59 -07:00
Lucien Greathouse
32af8783ba Update Changelog 2019-08-26 13:52:16 -07:00
Lucien Greathouse
d6f51f8eba Upgrade rbx_dom_lua 2019-08-26 13:52:06 -07:00
Lucien Greathouse
f40b7361e8 Update Changelog 2019-08-21 16:08:58 -07:00
Lucien Greathouse
0231e114d5 Upgrade rbx_dom_lua. Fixes #201. 2019-08-21 15:59:57 -07:00
Lucien Greathouse
ca61a3e83f Add test case for #201 2019-08-21 15:45:22 -07:00
Lucien Greathouse
6979f5c82d Add build tests for init Lua files 2019-08-16 12:50:11 -07:00
Lucien Greathouse
7d45b45667 Change JSON model naming behavior.
- JSON model names now come from the file name
- The 'Name' field is now optional for the top-level instance
- Snapshot tests run way faster by executing Rojo directly instead of Cargo
2019-08-15 14:09:16 -07:00
Lucien Greathouse
7575504b80 Add build test for JSON model 2019-08-14 18:03:19 -07:00
Lucien Greathouse
36bcb611f1 Port CSV regression tests to insta 2019-08-14 15:50:28 -07:00
Lucien Greathouse
cc34c36794 Add CSV snapshot test 2019-08-14 15:34:25 -07:00
Lucien Greathouse
b84cb93d2c Remove test warning 2019-08-14 15:33:00 -07:00
Lucien Greathouse
08211a7740 Add rbxm build test 2019-08-14 15:07:37 -07:00
Lucien Greathouse
97985dd458 Fix test warning that's been in the codebase forever 2019-08-13 11:00:33 -07:00
Lucien Greathouse
edf157215c docs: Embed RDC 2019 video into 'Why Rojo' page.
Closes #227.
2019-08-12 10:28:50 -07:00
Lucien Greathouse
89671c71fa Add basic rbxmx snapshot test 2019-08-10 00:52:16 -07:00
Lucien Greathouse
eeedcc50ab Update rbx-dom dependency URL 2019-08-08 21:36:21 -07:00
Lucien Greathouse
de0bb069aa Reduce Travis-CI build load
- Remove testing with --all-features, no features are supported
- Remove testing beta, it isn't useful and takes up valuable CI time
2019-08-08 21:08:10 -07:00
Lucien Greathouse
5d53f8bfb3 Add script build tests 2019-08-08 18:30:53 -07:00
Lucien Greathouse
d4a7de8070 Update dependencies 2019-08-08 16:57:01 -07:00
Lucien Greathouse
3fe15641c7 Ignore new insta snaps 2019-08-07 17:54:15 -07:00
Lucien Greathouse
08df71a7e4 Change rojo-test to be macro-based 2019-08-07 17:50:05 -07:00
Lucien Greathouse
77db25b4d9 Add end-to-end build tests 2019-08-07 17:41:17 -07:00
89 changed files with 2250 additions and 1113 deletions

30
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
rust_version: [stable, "1.40.0"]
steps:
- uses: actions/checkout@v1
- name: Setup Rust toolchain
run: rustup default ${{ matrix.rust_version }}
- name: Build
run: cargo build --locked --verbose
- name: Run tests
run: cargo test --locked --verbose
- name: Build (All Features)
run: cargo build --locked --verbose --all-features
- name: Run tests (All Features)
run: cargo test --locked --verbose --all-features

60
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: Release
on:
push:
tags: ["*"]
jobs:
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
- name: Build release binary
run: cargo build --verbose --locked --release
- name: Upload artifacts
uses: actions/upload-artifact@v1
with:
name: rojo-win64
path: target/release/rojo.exe
macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v1
- name: Install Rust
run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
- name: Build release binary
run: |
source $HOME/.cargo/env
cargo build --verbose --locked --release
env:
OPENSSL_STATIC: 1
- name: Upload artifacts
uses: actions/upload-artifact@v1
with:
name: rojo-macos
path: target/release/rojo
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Build
run: cargo build --locked --verbose --release
env:
OPENSSL_STATIC: 1
- name: Upload artifacts
uses: actions/upload-artifact@v1
with:
name: rojo-linux
path: target/release/rojo

3
.gitignore vendored
View File

@@ -5,4 +5,5 @@
/*.rbxm
/*.rbxmx
/*.rbxl
/*.rbxlx
/*.rbxlx
**/*.snap.new

2
.gitmodules vendored
View File

@@ -15,4 +15,4 @@
url = https://github.com/osyrisrblx/t.git
[submodule "plugin/modules/rbx-dom"]
path = plugin/modules/rbx-dom
url = http://github.com/LPGhatguy/rbx-dom
url = http://github.com/rojo-rbx/rbx-dom

View File

@@ -35,20 +35,10 @@ matrix:
script:
- cargo test --verbose
- cargo test --verbose --all-features
- language: rust
rust: stable
cache: cargo
script:
- cargo test --verbose
- cargo test --verbose --all-features
- language: rust
rust: beta
cache: cargo
script:
- cargo test --verbose
- cargo test --verbose --all-features
- cargo test --verbose

View File

@@ -1,6 +1,57 @@
# Rojo Changelog
## Unreleased Changes
* Updated reflection database and other dependencies.
## [0.5.4](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.4) (February 26, 2020)
This is a general maintenance release for the Rojo 0.5.x release series.
* Updated reflection database and other dependencies.
* First stable release with binaries for macOS and Linux.
## [0.6.0 Alpha 1](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.1) (January 22, 2020)
### General
* Added support for nested project files. ([#95](https://github.com/rojo-rbx/rojo/issues/95))
* Added project file hot-reloading. ([#10](https://github.com/rojo-rbx/rojo/issues/10)])
* Fixed Rojo dropping Ref properties ([#142](https://github.com/rojo-rbx/rojo/issues/142))
* This means that properties like `PrimaryPart` now work!
* Improved live sync protocol to reduce round-trips and improve syncing consistency.
* Improved support for binary model files and places.
### Command Line
* Added `--verbose`/`-v` flag, which can be specified multiple times to increase verbosity.
* Added support for automatically finding Roblox Studio's auth cookie for `rojo upload` on Windows.
* Added support for building, serving and uploading sources that aren't Rojo projects.
* Improved feedback from `rojo serve`.
* Removed support for legacy `roblox-project.json` projects, deprecated in an early Rojo 0.5.0 alpha.
* Rojo no longer traverses directories upwards looking for project files.
* Though undocumented, Rojo 0.5.x will search for a project file contained in any ancestor folders. This feature was removed to better support other 0.6.x features.
### Roblox Studio Plugin
* Added "connecting" state to improve experience when live syncing.
* Added "error" state to show errors in a place that isn't the output panel.
* Improved diagnostics for when the Rojo plugin cannot create an instance.
## [0.5.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.3) (October 15, 2019)
* Fixed an issue where Rojo would throw an error when encountering recently-added instance classes.
## [0.5.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.2) (October 14, 2019)
* Fixed an issue where `LocalizationTable` instances would have their column order randomized. ([#173](https://github.com/rojo-rbx/rojo/issues/173))
## [0.5.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.1) (October 4, 2019)
* Fixed an issue where Rojo would drop changes if they happened too quickly ([#252](https://github.com/rojo-rbx/rojo/issues/252))
* Improved diagnostics for when the Rojo plugin cannot create an instance.
* Updated dependencies
* This brings Rojo's reflection database from client release 395 to client release 404.
## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August 27, 2019)
* Changed `.model.json` naming, which may require projects to migrate ambiguous cases:
* The file name now takes precedence over the `Name` field in the model, like Rojo 0.4.x.
* The `Name` field of the top-level instance is now optional. It's recommended that you remove it from your models.
* Rojo will emit a warning when `Name` is specified and does not match the name from the file.
* Fixed `Rect` values being set to `0, 0, 0, 0` when synced with the Rojo plugin. ([#201](https://github.com/rojo-rbx/rojo/issues/201))
* Fixed live-syncing of `PhysicalProperties`, `NumberSequence`, and `ColorSequence` values
## [0.5.0 Alpha 13](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.13) (August 2, 2019)
* Bumped minimum Rust version to 1.34.0.

48
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,48 @@
# Contributing to the Rojo Project
Rojo is a big project and can always use more help! This guide covers all repositories underneath the [rojo-rbx organization on GitHub](https://github.com/rojo-rbx).
Some of the repositories covered are:
* https://github.com/rojo-rbx/rojo
* https://github.com/rojo-rbx/rbx-dom
* https://github.com/rojo-rbx/vscode-rojo
* https://github.com/rojo-rbx/rbxlx-to-rojo
## Code
Code contributions are welcome for features and bugs that have been reported in the project's bug tracker. We want to make sure that no one wastes their time, so be sure to talk with maintainers about what changes would be accepted before doing any work!
## Documentation
Documentation impacts way more people than the individual lines of code we write.
If you find any problems in documentation, including typos, bad grammar, misleading phrasing, or missing content, feel free to file issues and pull requests to fix them.
## Bug Reports and Feature Requests
Most of the tools around Rojo try to be clear when an issue is a bug. Even if they aren't, sometimes things don't work quite right.
Sometimes there's something that Rojo doesn't do that it probably should.
Please file issues and we'll try to help figure out what the best way forward is.
## Pushing a Rojo Release
The Rojo release process is pretty manual right now. If you need to do it, here's how:
1. Bump server version in [`server/Cargo.toml`](server/Cargo.toml)
2. Bump plugin version in [`plugin/src/Config.lua`](plugin/src/Config.lua)
3. Run `cargo test` to update `Cargo.lock` and double-check tests
4. Update [`CHANGELOG.md`](CHANGELOG.md)
5. Commit!
* `git add . && git commit -m "Release vX.Y.Z"`
6. Tag the commit with the version from `Cargo.toml` prepended with a v, like `v0.4.13`
7. Build Windows release build of CLI
* `cargo build --release`
7. Publish the CLI
* `cargo publish`
8. Build and upload the plugin
* `rojo build plugin -o Rojo.rbxm`
* Upload `Rojo.rbxm` to Roblox.com, keep it for later
9. Push commits and tags
* `git push && git push --tags`
10. Copy GitHub release content from previous release
* Update the leading text with a summary about the release
* Paste the changelog notes (as-is!) from [`CHANGELOG.md`](CHANGELOG.md)
* Write a small summary of each major feature

2226
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
[workspace]
members = [
"server",
"rojo-test",
]
[profile.dev]

View File

@@ -48,6 +48,8 @@ Soon, Rojo will be able to:
If you find any mistakes, feel free to make changes in the [docs](https://github.com/rojo-rbx/rojo/tree/master/docs) folder of this repository and submit a pull request!
## Contributing
Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions for helping work on Rojo!
Pull requests are welcome!
Rojo supports Rust 1.34.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has.

View File

@@ -26,12 +26,14 @@ The Rojo CLI must be run from the command line, like Terminal.app on MacOS or `c
### Installing from Cargo
If you have Rust installed, the easiest way to get Rojo is with Cargo!
To install the latest 0.5.0 alpha, use:
To install the latest 0.5.x release, use:
```sh
cargo install rojo --version 0.5.0-alpha.13
cargo install rojo
```
If you're upgrading from a previous version of Rojo, you may need to pass `--force` to tell Cargo to overwrite your existing version.
## Installing the Plugin
### Installing from GitHub
@@ -43,4 +45,4 @@ Download the attached `rbxm` file and put it into your Roblox Studio plugins fol
{: align="center" }
### Installing from Roblox.com
Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364/Rojo-0-5-0-alpha-3) in Roblox Studio and press **Install**.
Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364) in Roblox Studio and press **Install**.

View File

@@ -60,4 +60,4 @@ Unknown files are now ignored in Rojo instead of being converted to `StringValue
## Migrating `init.model.json` files
In Rojo 0.4.x, it's possible to create a file named `init.model.json` that lets you describe a model that becomes the container for all of the other files in the folder, just like `init.lua`.
In Rojo 0.5.x, this feature has been replaced with `init.meta.json` files. See [Sync Details](../reference/sync-details) for more information about these new files.
In Rojo 0.5.x, this feature has been replaced with `init.meta.json` files. See [Sync Details](../../reference/sync-details) for more information about these new files.

7
docs/help.md Normal file
View File

@@ -0,0 +1,7 @@
Rojo is a fairly complex tool to adopt, but there's a community willing to help!
The [Roblox Open Source Community Discord](https://discord.gg/wH5ncNS) currently hosts a Rojo support channel, **#rojo**, that is a great place to get help as problems come up.
If you find anything that looks like a bug or have ideas for how to improve Rojo, feel free to file an issue on [Rojo's GitHub issue tracker](https://github.com/rojo-rbx/rojo/issues).
Rojo's primary maintainer is also available on Twitter, [@LPGhatguy](https://twitter.com/LPGhatguy).

View File

@@ -1,11 +1,11 @@
This is the documentation home for Rojo 0.5.x.
This is the documentation home for **Rojo 0.5.x**.
Available versions of these docs:
* [Latest version (currently 0.5.x)](https://rojo.space/docs/latest)
* [Latest version from `master` branch](https://rojo.space/docs/latest)
* [0.5.x](https://rojo.space/docs/0.5.x)
* [0.4.x](https://rojo.space/docs/0.4.x)
**Rojo** is a flexible multi-tool designed for creating robust Roblox projects.
**Rojo** is a tool designed to enable Roblox developers to use professional-grade software engineering tools.
This documentation is a continual work in progress. If you find any issues, please file an issue on [Rojo's issue tracker](https://github.com/rojo-rbx/rojo/issues)!

View File

@@ -1,25 +1,31 @@
[TOC]
## Project File
Rojo projects are JSON files that have the `.project.json` extension. They have the following fields:
Rojo projects are JSON files that have the `.project.json` extension. They have these fields:
* `name`: A string indicating the name of the project.
* This is only used for diagnostics.
* `name`: A string indicating the name of the project. This name is used when building the project into a model or place file.
* **Required**
* `tree`: An [Instance Description](#instance-description) describing the root instance of the project.
* **Required**
* `servePort`: The port that `rojo serve` should listen on. Passing `--port` will override this setting.
* **Optional**
* Default is `34872`
* `servePlaceIds`: A list of place IDs that this project may be live-synced to. This feature can help prevent overwriting the wrong game with source from Rojo.
* **Optional**
* Default is `null`
## Instance Description
Instance Descriptions correspond one-to-one with the actual Roblox Instances in the project. They can be specified directly in the project file or be pulled from the filesystem.
Instance Descriptions correspond one-to-one with the actual Roblox Instances in the project.
* `$className`: The ClassName of the Instance being described.
* Optional if `$path` is specified.
* **Optional if `$path` is specified.**
* `$path`: The path on the filesystem to pull files from into the project.
* Optional if `$className` is specified.
* **Optional if `$className` is specified.**
* Paths are relative to the folder containing the project file.
* `$properties`: Properties to apply to the instance. Values should be [Instance Property Values](#instance-property-value).
* Optional
* **Optional**
* `$ignoreUnknownInstances`: Whether instances that Rojo doesn't know about should be deleted.
* Optional
* **Optional**
* Default is `false` if `$path` is specified, otherwise `true`.
All other fields in an Instance Description are turned into instances whose name is the key. These values should also be Instance Descriptions!

View File

@@ -86,6 +86,11 @@ It would turn into instances in this shape:
![Tree of instances in Roblox](../images/sync-example-json-model.svg)
{: align="center" }
!!! warning
Starting in Rojo 0.5.0 (stable), the `Name` field is no longer required. The name of the top-level instance in a JSON model is now based on its file name, and the `Name` field is now ignored.
Rojo will emit a warning if the `Name` field is specified and does not match the file's name.
## Binary and XML Models
Rojo supports both binary (`.rbxm`) and XML (`.rbxmx`) models generated by Roblox Studio or another tool.
@@ -111,10 +116,18 @@ Meta files can contain:
### Meta Files to set Rojo metadata
Sometimes it's useful to apply properties like `ignoreUnknownInstances` on instances that are defined on the filesystem instead of within the project itself.
If your project has `hello.txt` and there are instances underneath it that you want Rojo to ignore when live-syncing, you could create `hello.meta.json` with:
```json
{
"ignoreUnknownInstances": true
}
```
### Meta Files for Disabled Scripts
Meta files can be used to set properties on `Script` instances, like `Disabled`.
If your project had `foo.server.lua` and you wanted to make sure it would be disabled, you could create a `foo.meta.json` next to it with:
If your project has `foo.server.lua` and you want to make sure it would be disabled, you could create a `foo.meta.json` next to it with:
```json
{
@@ -135,7 +148,7 @@ If you wanted to represent a tool containing a script and a model for its handle
0, 0, 0,
1, 0, 0,
0, 1, 0,
0, 0, 1,
0, 0, 1
]
}
}

View File

@@ -2,6 +2,11 @@ Adding a tool like Rojo to your Roblox workflow can be daunting, but it comes wi
[TOC]
## Rojo at RDC 2019
Nathan Riemer (Kampfkarren) gave a talk at RDC 2019 talking about some of the benefits of using a tool like Rojo.
<iframe style="margin: 0 auto; max-width: 100%" width="560" height="315" src="https://www.youtube-nocookie.com/embed/czlvzEyhaBc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
## External Text Editors
Rojo opens the door to use the absolute best text editors in the world and their rich plugin ecosystems.

View File

@@ -11,6 +11,7 @@ theme:
nav:
- Home: index.md
- Why Rojo?: why-rojo.md
- Get Help with Rojo: help.md
- Guide:
- Installation: guide/installation.md
- Creating a Game with Rojo: guide/new-game.md

View File

@@ -131,13 +131,15 @@ function ApiContext:read(ids)
return Promise.reject("Server changed ID")
end
self.messageCursor = body.messageCursor
return body
end)
end
function ApiContext:retrieveMessages()
function ApiContext:retrieveMessages(initialCursor)
if initialCursor ~= nil then
self.messageCursor = initialCursor
end
local url = ("%s/api/subscribe/%s"):format(self.baseUrl, self.messageCursor)
local function sendRequest()

View File

@@ -1,6 +1,6 @@
return {
codename = "Epiphany",
version = {0, 5, 0, "-alpha.13"},
version = {0, 5, 4},
expectedServerVersionString = "0.5.0 or newer",
protocolVersion = 2,
defaultHost = "localhost",

View File

@@ -50,6 +50,8 @@ function Reconciler:reconcile(virtualInstancesById, id, instance)
-- If an instance changes ClassName, we assume it's very different. That's
-- not always the case!
if virtualInstance.ClassName ~= instance.ClassName then
Logging.trace("Switching to reify for %s because ClassName is different", instance:GetFullName())
-- TODO: Preserve existing children instead?
local parent = instance.Parent
self.instanceMap:destroyId(id)
@@ -93,6 +95,12 @@ function Reconciler:reconcile(virtualInstancesById, id, instance)
unvisitedExistingChildren[existingChildInstance] = nil
self:reconcile(virtualInstancesById, childId, existingChildInstance)
else
Logging.trace(
"Switching to reify for %s.%s because it does not exist",
instance:GetFullName(),
virtualInstancesById[childId].Name
)
self:__reify(virtualInstancesById, childId, instance)
end
end
@@ -148,7 +156,13 @@ function Reconciler:__reify(virtualInstancesById, id, parent)
local virtualInstance = virtualInstancesById[id]
local instance = Instance.new(virtualInstance.ClassName)
local ok, instance = pcall(function()
return Instance.new(virtualInstance.ClassName)
end)
if not ok then
error(("Couldn't create an Instance of type %q, a child of %s"):format(virtualInstance.ClassName, parent:GetFullName()))
end
for key, value in pairs(virtualInstance.Properties) do
setCanonicalProperty(instance, key, rojoValueToRobloxValue(value))

View File

@@ -33,7 +33,7 @@ function Session.new(config)
end
self.reconciler:reconcile(response.instances, api.rootInstanceId, game)
return self:__processMessages()
return self:__processMessages(response.messageCursor)
end)
:catch(function(message)
self.disconnected = true
@@ -43,12 +43,12 @@ function Session.new(config)
return not self.disconnected, setmetatable(self, Session)
end
function Session:__processMessages()
function Session:__processMessages(initialCursor)
if self.disconnected then
return Promise.resolve()
end
return self.api:retrieveMessages()
return self.api:retrieveMessages(initialCursor)
:andThen(function(messages)
local promise = Promise.resolve(nil)

14
rojo-test/Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[package]
name = "rojo-test"
version = "0.1.0"
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
edition = "2018"
publish = false
[dependencies]
insta = "0.10.0"
paste = "0.1.5"
tempfile = "3.1.0"
# We execute Rojo via std::process::Command, so depend on it so it's built!
rojo = { path = "../server" }

View File

@@ -0,0 +1,6 @@
{
"name": "client_in_folder",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1 @@
-- This is a Lua client script

View File

@@ -0,0 +1,6 @@
{
"name": "client_init",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1 @@
return "From folder/init.client.lua"

View File

@@ -0,0 +1,6 @@
{
"name": "csv_bug_145",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1,6 @@
{
"name": "csv_bug_147",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1,6 @@
{
"name": "csv_in_folder",
"tree": {
"$path": "folder"
}
}

View File

@@ -1,5 +1,5 @@
{
"name": "localization",
"name": "gitkeep",
"tree": {
"$path": "src"
}

View File

@@ -0,0 +1,6 @@
{
"name": "init_meta_class_name",
"tree": {
"$path": "should-be-a-model"
}
}

View File

@@ -0,0 +1,3 @@
{
"className": "Model"
}

View File

@@ -0,0 +1,6 @@
{
"className": "Lighting",
"properties": {
"Technology": "Voxel"
}
}

View File

@@ -0,0 +1,6 @@
{
"name": "init_meta_properties",
"tree": {
"$path": "Lighting"
}
}

View File

@@ -0,0 +1,6 @@
{
"name": "json_model_in_folder",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1,12 @@
{
"ClassName": "IntValue",
"Properties": {
"Value": 5
},
"Children": [
{
"Name": "A Child",
"ClassName": "Folder"
}
]
}

View File

@@ -0,0 +1,6 @@
{
"name": "json_model_legacy_name",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1,4 @@
{
"Name": "Overridden Name",
"ClassName": "Folder"
}

View File

@@ -0,0 +1,6 @@
{
"name": "module_in_folder",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1 @@
-- This is a Lua module

View File

@@ -0,0 +1,6 @@
{
"name": "module_init",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1 @@
return "From folder/init.lua"

View File

@@ -0,0 +1,6 @@
{
"name": "rbxm_in_folder",
"tree": {
"$path": "folder"
}
}

Binary file not shown.

View File

@@ -0,0 +1,6 @@
{
"name": "rbxmx_in_folder",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1,33 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<Meta name="ExplicitAutoJoints">true</Meta>
<External>null</External>
<External>nil</External>
<Item class="Model" referent="RBX7E9D90237E87493FB533B16578969429">
<Properties>
<CoordinateFrame name="ModelInPrimary">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<string name="Name">Awesome Model</string>
<Ref name="PrimaryPart">null</Ref>
<BinaryString name="Tags"></BinaryString>
</Properties>
<Item class="StringValue" referent="RBXD2A682F437C84BE89C7B356CF5E4D92E">
<Properties>
<string name="Name">Cool StringValue</string>
<BinaryString name="Tags"></BinaryString>
<string name="Value">Did you know that BaseValue.Changed is different than Instance.Changed?</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,6 @@
{
"name": "script_meta_disabled",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1,5 @@
{
"properties": {
"Disabled": true
}
}

View File

@@ -0,0 +1 @@
-- This script should be marked 'Disabled'

View File

@@ -0,0 +1,6 @@
{
"name": "server_in_folder",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1 @@
-- This is a Lua server script

View File

@@ -0,0 +1,6 @@
{
"name": "server_init",
"tree": {
"$path": "folder"
}
}

View File

@@ -0,0 +1 @@
return "From folder/init.server.lua"

View File

@@ -0,0 +1,6 @@
{
"name": "txt_in_folder",
"tree": {
"$path": "src"
}
}

View File

@@ -0,0 +1,72 @@
use std::{fs, path::Path, process::Command};
use insta::assert_snapshot_matches;
use tempfile::tempdir;
macro_rules! gen_build_tests {
( $($test_name: ident,)* ) => {
$(
paste::item! {
#[test]
fn [<build_ $test_name>]() {
run_build_test(stringify!($test_name));
}
}
)*
};
}
gen_build_tests! {
client_in_folder,
client_init,
csv_bug_145,
csv_bug_147,
csv_in_folder,
gitkeep,
init_meta_class_name,
init_meta_properties,
json_model_in_folder,
json_model_legacy_name,
module_in_folder,
module_init,
rbxm_in_folder,
rbxmx_in_folder,
script_meta_disabled,
server_in_folder,
server_init,
txt_in_folder,
}
fn run_build_test(test_name: &str) {
let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
let build_test_path = manifest_dir.join("build-tests");
let working_dir = manifest_dir.parent().unwrap();
let output_dir = tempdir().expect("couldn't create temporary directory");
let input_path = build_test_path.join(test_name);
let output_path = output_dir.path().join(format!("{}.rbxmx", test_name));
let mut exe_path = working_dir.join("target/debug/rojo");
if cfg!(windows) {
exe_path.set_extension("exe");
}
let status = Command::new(exe_path)
.args(&[
"build",
input_path.to_str().unwrap(),
"-o",
output_path.to_str().unwrap(),
])
.env("RUST_LOG", "error")
.current_dir(working_dir)
.status()
.expect("Couldn't start Rojo");
assert!(status.success(), "Rojo did not exit successfully");
let contents = fs::read_to_string(&output_path).expect("Couldn't read output file");
assert_snapshot_matches!(test_name, contents);
}

2
rojo-test/src/lib.rs Normal file
View File

@@ -0,0 +1,2 @@
#[cfg(test)]
mod build_test;

View File

@@ -0,0 +1,19 @@
---
created: "2019-08-09T01:29:47.650277200Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">client_in_folder</string>
</Properties>
<Item class="LocalScript" referent="1">
<Properties>
<string name="Name">localScript</string>
<string name="Source">-- This is a Lua client script</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,14 @@
---
created: "2019-08-16T19:37:51.277332900Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="LocalScript" referent="0">
<Properties>
<string name="Name">client_init</string>
<string name="Source">return "From folder/init.client.lua"</string>
</Properties>
</Item>
</roblox>

View File

@@ -0,0 +1,19 @@
---
created: "2019-08-14T22:42:52.297447700Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">csv_bug_145</string>
</Properties>
<Item class="LocalizationTable" referent="1">
<Properties>
<string name="Name">normal</string>
<string name="Contents">[{"key":"Count","example":"A number demonstrating issue 145","source":"3","values":{"es":"7"}}]</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,19 @@
---
created: "2019-08-14T22:42:52.310414Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">csv_bug_147</string>
</Properties>
<Item class="LocalizationTable" referent="1">
<Properties>
<string name="Name">normal</string>
<string name="Contents">[{"key":"Language.Name","source":"English","values":{}},{"key":"Language.Region","source":"United States","values":{}},{"key":"Label.Thickness","source":"Thickness","values":{}},{"key":"Label.Opacity","source":"Opacity","values":{}},{"key":"Toolbar.Undo","source":"Undo","values":{}},{"key":"Toolbar.Redo","source":"Redo","values":{}},{"key":"Toolbar.Camera","source":"Top-down camera","values":{}},{"key":"Toolbar.Saves","source":"Saved drawings","values":{}},{"key":"Toolbar.Preferences","source":"Settings","values":{}},{"key":"Toolbar.Mode.Vector","source":"Vector mode","values":{}},{"key":"Toolbar.Mode.Pixel","source":"Pixel mode","values":{}}]</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,19 @@
---
created: "2019-08-14T22:34:06.206495600Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">csv_in_folder</string>
</Properties>
<Item class="LocalizationTable" referent="1">
<Properties>
<string name="Name">normal</string>
<string name="Contents">[{"key":"Ack","example":"An exclamation of despair","source":"Ack!","values":{"es":"¡Ay!"}}]</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,13 @@
---
created: "2019-08-08T00:48:33.382271800Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">gitkeep</string>
</Properties>
</Item>
</roblox>

View File

@@ -0,0 +1,11 @@
---
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Model" referent="0">
<Properties>
<string name="Name">init_meta_class_name</string>
</Properties>
</Item>
</roblox>

View File

@@ -0,0 +1,12 @@
---
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Lighting" referent="0">
<Properties>
<string name="Name">init_meta_properties</string>
<token name="Technology">1</token>
</Properties>
</Item>
</roblox>

View File

@@ -0,0 +1,24 @@
---
created: "2019-08-15T20:40:50.467761900Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">json_model_in_folder</string>
</Properties>
<Item class="IntValue" referent="1">
<Properties>
<string name="Name">simple-model</string>
<int name="Value">5</int>
</Properties>
<Item class="Folder" referent="2">
<Properties>
<string name="Name">A Child</string>
</Properties>
</Item>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,18 @@
---
created: "2019-08-15T20:41:28.743618200Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">json_model_legacy_name</string>
</Properties>
<Item class="Folder" referent="1">
<Properties>
<string name="Name">Expected Name</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,19 @@
---
created: "2019-08-09T01:27:22.597759700Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">module_in_folder</string>
</Properties>
<Item class="ModuleScript" referent="1">
<Properties>
<string name="Name">aModule</string>
<string name="Source">-- This is a Lua module</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,14 @@
---
created: "2019-08-16T19:36:55.442461700Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="ModuleScript" referent="0">
<Properties>
<string name="Name">module_init</string>
<string name="Source">return "From folder/init.lua"</string>
</Properties>
</Item>
</roblox>

View File

@@ -0,0 +1,18 @@
---
created: "2019-08-14T22:05:46.597722600Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">rbxm_in_folder</string>
</Properties>
<Item class="Folder" referent="1">
<Properties>
<string name="Name">foo</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,43 @@
---
created: "2020-02-27T02:00:43.519025Z"
creator: insta@0.10.1
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">rbxmx_in_folder</string>
</Properties>
<Item class="Model" referent="1">
<Properties>
<string name="Name">test-model</string>
<CoordinateFrame name="ModelInPrimary">
<X>0</X>
<Y>0</Y>
<Z>0</Z>
<R00>1</R00>
<R01>0</R01>
<R02>0</R02>
<R10>0</R10>
<R11>1</R11>
<R12>0</R12>
<R20>0</R20>
<R21>0</R21>
<R22>1</R22>
</CoordinateFrame>
<Ref name="PrimaryPart">null</Ref>
<BinaryString name="Tags">
</BinaryString>
</Properties>
<Item class="StringValue" referent="2">
<Properties>
<string name="Name">Cool StringValue</string>
<BinaryString name="Tags">
</BinaryString>
<string name="Value">Did you know that BaseValue.Changed is different than Instance.Changed?</string>
</Properties>
</Item>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,18 @@
---
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">script_meta_disabled</string>
</Properties>
<Item class="Script" referent="1">
<Properties>
<string name="Name">hello</string>
<bool name="Disabled">true</bool>
<string name="Source">-- This script should be marked 'Disabled'</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,19 @@
---
created: "2019-08-09T01:29:48.071133300Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">server_in_folder</string>
</Properties>
<Item class="Script" referent="1">
<Properties>
<string name="Name">serverScript</string>
<string name="Source">-- This is a Lua server script</string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -0,0 +1,14 @@
---
created: "2019-08-16T19:36:55.442461700Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Script" referent="0">
<Properties>
<string name="Name">server_init</string>
<string name="Source">return "From folder/init.server.lua"</string>
</Properties>
</Item>
</roblox>

View File

@@ -0,0 +1,19 @@
---
created: "2019-08-08T00:48:33.502257600Z"
creator: insta@0.10.0
source: rojo-test/src/build_test.rs
expression: contents
---
<roblox version="4">
<Item class="Folder" referent="0">
<Properties>
<string name="Name">txt_in_folder</string>
</Properties>
<Item class="StringValue" referent="1">
<Properties>
<string name="Name">foo</string>
<string name="Value"></string>
</Properties>
</Item>
</Item>
</roblox>

View File

@@ -1,6 +1,6 @@
[package]
name = "rojo"
version = "0.5.0-alpha.13"
version = "0.5.4"
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
description = "Enables professional-grade development tools for Roblox developers"
license = "MIT"

View File

@@ -3,7 +3,7 @@
use std::{
borrow::Cow,
collections::HashMap,
collections::{BTreeMap, HashMap},
fmt,
path::{Path, PathBuf},
str,
@@ -631,7 +631,8 @@ fn snapshot_csv_file<'source>(
#[serde(skip_serializing_if = "Option::is_none")]
source: Option<&'a str>,
values: HashMap<&'a str, &'a str>,
// We use a BTreeMap here to get deterministic output order.
values: BTreeMap<&'a str, &'a str>,
}
let instance_name = file.path
@@ -724,28 +725,63 @@ fn snapshot_csv_file<'source>(
fn snapshot_json_model_file<'source>(
file: &'source ImfsFile,
) -> SnapshotResult<'source> {
let file_name = file.path
.file_name().expect("Could not extract file stem")
.to_str().expect("Could not convert path to UTF-8");
let instance_name = match_trailing(file_name, ".model.json")
.expect("JSON model file did not end in .model.json");
let contents = str::from_utf8(&file.contents)
.map_err(|inner| SnapshotError::Utf8Error {
inner,
path: file.path.to_owned(),
})?;
let json_instance: JsonModelInstance = serde_json::from_str(contents)
let json_instance: JsonModel = serde_json::from_str(contents)
.map_err(|inner| SnapshotError::JsonModelDecodeError {
inner,
path: file.path.to_owned(),
})?;
let mut snapshot = json_instance.into_snapshot()?;
if let Some(json_name) = &json_instance.name {
if json_name != instance_name {
log::warn!("Name from JSON model did not match its file name: {}", file.path.display());
log::warn!("In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", json_name);
log::warn!("In Rojo >= alpha 14, this model is named \"{}\" (from its file name)", instance_name);
log::warn!("'Name' for the top-level instance in a JSON model is now optional and will be ignored.");
}
}
let mut snapshot = json_instance.core.into_snapshot(instance_name.to_owned())?;
snapshot.name = Cow::Borrowed(instance_name);
snapshot.metadata.source_path = Some(file.path.to_owned());
Ok(Some(snapshot))
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct JsonModel {
name: Option<String>,
#[serde(flatten)]
core: JsonModelCore,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct JsonModelInstance {
name: String,
#[serde(flatten)]
core: JsonModelCore,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
struct JsonModelCore {
class_name: String,
#[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")]
@@ -755,12 +791,12 @@ struct JsonModelInstance {
properties: HashMap<String, UnresolvedRbxValue>,
}
impl JsonModelInstance {
fn into_snapshot(self) -> Result<RbxSnapshotInstance<'static>, SnapshotError> {
impl JsonModelCore {
fn into_snapshot(self, name: String) -> Result<RbxSnapshotInstance<'static>, SnapshotError> {
let mut children = Vec::with_capacity(self.children.len());
for child in self.children {
children.push(child.into_snapshot()?);
children.push(child.core.into_snapshot(child.name)?);
}
let mut properties = HashMap::with_capacity(self.properties.len());
@@ -771,7 +807,7 @@ impl JsonModelInstance {
}
Ok(RbxSnapshotInstance {
name: Cow::Owned(self.name),
name: Cow::Owned(name),
class_name: Cow::Owned(self.class_name),
properties,
children,

View File

@@ -73,7 +73,7 @@ impl InterfaceService {
<h2 class="subtitle">
"Version " { self.server_version }
</h2>
<a class="docs" href="https://lpghatguy.github.io/rojo">
<a class="docs" href="https://rojo.space/docs">
"Rojo Documentation"
</a>
</div>

View File

@@ -2,7 +2,6 @@ mod test_util;
use std::collections::HashMap;
use pretty_assertions::assert_eq;
use rbx_dom_weak::{RbxTree, RbxInstanceProperties};
use librojo::{

View File

@@ -2,8 +2,6 @@ mod test_util;
use std::path::Path;
use pretty_assertions::assert_eq;
use librojo::{
imfs::Imfs,
project::Project,
@@ -34,7 +32,6 @@ macro_rules! generate_snapshot_tests {
generate_snapshot_tests!(
empty,
json_model,
localization,
meta_files,
multi_partition_game,
nested_partitions,

View File

@@ -1,69 +0,0 @@
{
"name": "localization",
"class_name": "Folder",
"properties": {},
"children": [
{
"name": "empty-column-bug-147",
"class_name": "LocalizationTable",
"properties": {
"Contents": {
"Type": "String",
"Value": "[{\"key\":\"Language.Name\",\"source\":\"English\",\"values\":{}},{\"key\":\"Language.Region\",\"source\":\"United States\",\"values\":{}},{\"key\":\"Label.Thickness\",\"source\":\"Thickness\",\"values\":{}},{\"key\":\"Label.Opacity\",\"source\":\"Opacity\",\"values\":{}},{\"key\":\"Toolbar.Undo\",\"source\":\"Undo\",\"values\":{}},{\"key\":\"Toolbar.Redo\",\"source\":\"Redo\",\"values\":{}},{\"key\":\"Toolbar.Camera\",\"source\":\"Top-down camera\",\"values\":{}},{\"key\":\"Toolbar.Saves\",\"source\":\"Saved drawings\",\"values\":{}},{\"key\":\"Toolbar.Preferences\",\"source\":\"Settings\",\"values\":{}},{\"key\":\"Toolbar.Mode.Vector\",\"source\":\"Vector mode\",\"values\":{}},{\"key\":\"Toolbar.Mode.Pixel\",\"source\":\"Pixel mode\",\"values\":{}}]"
}
},
"children": [],
"metadata": {
"ignore_unknown_instances": false,
"source_path": "src/empty-column-bug-147.csv",
"project_definition": null
}
},
{
"name": "integers-bug-145",
"class_name": "LocalizationTable",
"properties": {
"Contents": {
"Type": "String",
"Value": "[{\"key\":\"Count\",\"example\":\"A number demonstrating issue 145\",\"source\":\"3\",\"values\":{\"es\":\"7\"}}]"
}
},
"children": [],
"metadata": {
"ignore_unknown_instances": false,
"source_path": "src/integers-bug-145.csv",
"project_definition": null
}
},
{
"name": "normal",
"class_name": "LocalizationTable",
"properties": {
"Contents": {
"Type": "String",
"Value": "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]"
}
},
"children": [],
"metadata": {
"ignore_unknown_instances": false,
"source_path": "src/normal.csv",
"project_definition": null
}
}
],
"metadata": {
"ignore_unknown_instances": false,
"source_path": "src",
"project_definition": [
"localization",
{
"class_name": null,
"children": {},
"properties": {},
"ignore_unknown_instances": null,
"path": "src"
}
]
}
}

View File

@@ -0,0 +1,12 @@
{
"name": "slice-center-gh-201",
"tree": {
"$className": "DataModel",
"ReplicatedStorage": {
"$className": "ReplicatedStorage",
"$path": "folder"
}
}
}

View File

@@ -0,0 +1,89 @@
<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
<Meta name="ExplicitAutoJoints">true</Meta>
<External>null</External>
<External>nil</External>
<Item class="ImageLabel" referent="RBXBB7AE810E3EE49438CCAA4DF1409C167">
<Properties>
<bool name="Active">false</bool>
<Vector2 name="AnchorPoint">
<X>0</X>
<Y>0</Y>
</Vector2>
<bool name="AutoLocalize">true</bool>
<Color3 name="BackgroundColor3">
<R>1</R>
<G>1</G>
<B>1</B>
</Color3>
<float name="BackgroundTransparency">0</float>
<Color3 name="BorderColor3">
<R>0.105882362</R>
<G>0.164705887</G>
<B>0.207843155</B>
</Color3>
<token name="BorderMode">0</token>
<int name="BorderSizePixel">1</int>
<bool name="ClipsDescendants">false</bool>
<bool name="Draggable">false</bool>
<Content name="Image"><url>rbxasset://textures/ui/GuiImagePlaceholder.png</url></Content>
<Color3 name="ImageColor3">
<R>1</R>
<G>1</G>
<B>1</B>
</Color3>
<Vector2 name="ImageRectOffset">
<X>0</X>
<Y>0</Y>
</Vector2>
<Vector2 name="ImageRectSize">
<X>0</X>
<Y>0</Y>
</Vector2>
<float name="ImageTransparency">0</float>
<int name="LayoutOrder">0</int>
<string name="Name">ImageLabel</string>
<Ref name="NextSelectionDown">null</Ref>
<Ref name="NextSelectionLeft">null</Ref>
<Ref name="NextSelectionRight">null</Ref>
<Ref name="NextSelectionUp">null</Ref>
<UDim2 name="Position">
<XS>0</XS>
<XO>0</XO>
<YS>0</YS>
<YO>0</YO>
</UDim2>
<Ref name="RootLocalizationTable">null</Ref>
<float name="Rotation">0</float>
<token name="ScaleType">1</token>
<bool name="Selectable">false</bool>
<Ref name="SelectionImageObject">null</Ref>
<UDim2 name="Size">
<XS>0</XS>
<XO>100</XO>
<YS>0</YS>
<YO>100</YO>
</UDim2>
<token name="SizeConstraint">0</token>
<Rect2D name="SliceCenter">
<min>
<X>1</X>
<Y>2</Y>
</min>
<max>
<X>3</X>
<Y>4</Y>
</max>
</Rect2D>
<float name="SliceScale">1</float>
<BinaryString name="Tags"></BinaryString>
<UDim2 name="TileSize">
<XS>1</XS>
<XO>0</XO>
<YS>1</YS>
<YO>0</YO>
</UDim2>
<bool name="Visible">true</bool>
<int name="ZIndex">1</int>
</Properties>
</Item>
</roblox>