If the sync lock is claimed in Team Create, the user cannot sync.
Therefore, a sync reminder notification is unhelpful as it is calling to
an invalid action.
Windows and macOS runners consume GitHub Actions minutes at [2x and 10x
the rate of Linux runners,
respectively](https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#minute-multipliers).
This is a bit concerning now that there are two Windows jobs and two
macOS jobs, introduced in #825.
This PR aims to reduce the cost by:
* Adding [rust-cache](https://github.com/Swatinem/rust-cache/) to reduce
the amount of time spent. I'm aware there were some concerns raised
about CI caches in general in #496 - are they still a blocker?
* Removing the unnecessary Windows and macOS MSRV build jobs. If an MSRV
build fails on one platform due to usage of new language features, then
it will fail on all of them.
@Kampfkarren may have to change this repository's required status checks
before this PR can be merged
This is a fairly important test verifying whether the action of moving a
folder into a watched folder is correctly detected and processed. It was
disabled in
b43b45be8f.
The fact that it failed indicates a possible bug in change processing,
so in this PR, I'll re-enable the test, investigate why it fails, and
fix it.
This PR adds macOS and Windows jobs to the CI workflow. This allows us
to see when changes break functionality on any supported platform, which
is particularly important for changes that involve the file system or
file watcher.
Right now, serve tests will fail when Rojo is built with the FSEvent
backend. The cause is essentially due to the fact that `/var` (where
temporary directories for serve tests are located) on macOS is actually
a symlink to `/private/var`. Paths coming from FSEvent always have
symlinks expanded, but Rojo never expands symlinks. So, Rojo's paths
during these tests look like `/var/*` while the FSEvent paths look like
`/private/var/*`. When Rojo's change processor receives these events, it
considers them outside the project and does not apply any changes,
causing serve tests to time out.
To work around this, we can call `Path::canonicalize` before passing the
project path to `rojo serve` during serve tests. Rojo does need to
better support symlinks (which would also solve the problem), but I
think that can be left for another day because it's larger in scope and
I mostly just want working tests before addressing #609.
Brings over some changes to rbx_dom_lua to validate attribute names
before calling `Instance:SetAttribute`. This should prevent Rojo from
falling over when it attempts to sync an attribute with an invalid name.
These warnings always appear for properties like `Capabilities`,
`SourceAssetId`, etc. and tend to scare users who are syncing models.
This information is now surfaced in the patch visualizer, so I think
these warnings can be demoted to debug logs.
Due to the rewrite of the plugin's core sync loop and the change for the
Notify backend on MacOS, along with all the other changes in 7.4.0, it
makes sense for us to use a release candidate before actually cutting a
proper `7.4.0` release.
This modifies Rojo's build script to throw a fit if we're building a
plugin with a semver incompatible version. In the process, it moves the
version of the plugin to a file named `Version.txt` that's parsed at
runtime. This should be minimally invasive but it's technically worse
for performance than the hardcoded table and string we had before.
This feels better than a CI check or just manually verifying because it
makes it physically impossible for us to forget since Rojo won't build
with it being wrong.
This PR aims to clean up the changelog in preparation for 7.4.0. We
should focus on making changes clear to users with examples, removing
any entries that they won't care about, and consolidating tightly
related changes
---------
Co-authored-by: boatbomber <zack@boatbomber.com>
Co-authored-by: Micah <48431591+nezuo@users.noreply.github.com>
Resolves#667
This PR:
- Introduces a new field in the project file: `scriptType` which has the
default value of `Class` (in parity with previous versions), but can
also be `RunContext`.
- This is then passed to `InstanceContext` from the `Project` struct.
- This then changes the RunContext in the lua `snapshot_middleware`
---------
Co-authored-by: Micah <dekkonot@rocketmail.com>
Because Roact will destroy and recreate a plugin widget if it unmounts
and remounts, Studio will complain about making a new widget with the
same ID as the old one.
The simplest solution is to just use GUIDs so we never have to worry
about this again. The ID is used internally for storing the widget's
dock state and other internal details, so we don't want *all* our
widgets to use GUIDs, only the ephemeral popup ones.
Services, `StarterPlayerScripts`, and `StarterCharacterScripts` are
currently special-cased to allow them to be specified in project files
without a classname. This does the same to `Terrain` since it's a
singleton in the same style as those.
The last release of rbx_dom had support for `Terrain.MaterialColors`.
This allows it to be specified directly instead of only via the
fully-qualified syntax.
When building the tree, I've implemented a few improvements:
- We no longer traverse the full ancestry for every leaf node- we exit
early when we find a node that already exists
- We no longer search the entire tree to see if a node id exists before
creating one with that id, we just check if is in the map
TOML maps well to Lua, is easier to read and write than JSON, and is
commonly used by Roblox tools.
Use cases:
* Put game, plugin, or library config in a toml file
* Sync in toml files generated by tools
* Sync in config files for tools so that the game can double-check that
the config file has been followed. (e.g. check that packages match
versions specified in wally.toml)
- Reconciler now has precommit and postcommit hooks for patch applying
- This is used to compute a patch tree snapshot precommit and update the
tree metadata postcommit
- PatchVisualizer can now display Removes that happened during sync
- It was previously missing because the removed objects no longer
existed so it couldn't get any info on them (This is resolved because
the info is gotten in precommit, before the instance was removed)
- PatchVisualizer now shows Old and New values instead of just Incoming
during sync
- (Still displays Current and Incoming during confirmation)
- This is much more useful, since you now see what the changes were and
not just which things were changed
- PatchVisualizer displays clarifying message when initial sync has no
changes instead of just showing a blank box
- Objects in the tree UI no longer get stuck expanded when the next
patch has the same instance but different info on it
- Objects in the tree UI correctly become selectable after their
instance is added and unclickable when removed during sync
Ref now is an optional inside, so it's redundant to have an option
wrapping an option. The only snapshots that were changed were any that
had a Ref within (from none to zeroed). Some also had some newlines
added in the end.
When an object is deleted in a patch, it is either represented with an
ID or an Instance. On initial sync, removals are instances since the map
does not contain those instances. Later removals of managed objects use
an ID. The patch visualizer only handled instances, so this fixes that.
Closes#710.
- Fixed an edge case where disconnecting and then reconnecting would
retain outdated info
- Fixed an issue where new patches wouldn't immediately update the
change info text
- Removed extraneous changes count info, as it was not useful and could
be checked in the visualizer anyway
- Added warning info for when some changes fail to apply
- Updates timestamp of last sync even if patch was empty, to have a more
accurate signal on Rojo's uptime
Closes#672.
Skips the user confirmation if the patch contains only a datamodel name
change.
I decided to build generic PatchSet utility functions in case we need to
use similar logic in the future, in addition to maintaining clear
division of duties. The app code shouldn't be too dependent upon patch
internal structure when we can avoid it.
---------
Co-authored-by: Kenneth Loeffler <kenloef@gmail.com>
Fixes macOS aarch64 builds not actually outputting x86 binaries by
specifying the `--target` flag during compilation in the release
workflow. These are the same changes as [this PR in
Aftman](https://github.com/LPGhatguy/aftman/pull/34), which had the same
issue, and uses the same workflow.
Why if you want to use ssh you need todo more setup aka add a ssh key
into github while with https you don't have to do the extra work aka
makes rojo easier to contribute to.
Clicking on the "X changes X ago" message opens up a handy diff
visualizer to see what those changes were. However, it had quite a few
issues that needed fixing.
- Disconnecting a session with it expanded caused an error as it tried
to read the serveSession that no longer exists during the page fade
transition. (#671)
- Resolved by converting to stateful component and holding the
serveSession during the lifetime to ensure it can render the last known
changes during the fade transition
- Leaving it open while new changes are synced did not update the
visualizer
- The patch data was piggybacking on an existing binding, which meant
that new patches did not trigger rerender.
- Resolved by converting to state
- Also made some improvements to that old binding
- Moved from app to connected page for better organization and
separation of duties
- No more useless updates causing rerenders with no real change
- Scroll window child component wouldn't actually display the updated
visuals
- Resolved by making major improvements to VirtualScroller
- Made more robust against edge case states
- Made smarter about knowing when it needs to refresh
As you can see in this slow motion GIF, it works now.

When a session is disconnected, the apiContext long-polling for messages
continues until resolved/rejected. This means that even after a session
is disconnected, a message can be received and handled.
This leads to bad behavior, as the session was already cleaned up and
the message cannot be handled correctly. The instance map was cleaned up
upon disconnect, so it will warn about unapplied changes to unknown
instances. (Like #512)
It's very easy to repro:
Connect a session, disconnect it, then save a change.
https://github.com/rojo-rbx/rojo/assets/40185666/846a7269-7043-4727-9f9c-b3ac55a18a3a
-----------
This PR fixes that neatly by tracking all active requests in a map, and
cancelling their promises when we disconnect.
Alright, so I hate to be the one to do this, but #584 broke crates.io
publishing and also caused librojo to be unusable. I see that there was
some discussion on Discord shortly after the problem was realized, but
there was no action taken.
I think keeping librojo and publishing working far, far outweigh any
convenience added by Wally.
I've kept the same `Packages` naming convention to keep the diff
minimal.
This PR brings two performance improvements to the `rojo sourcemap`
command:
- Use `rayon` with a small threadpool to parallelize sourcemap
generation while still keeping startup cost very low
- Remove conversions to owned strings and use lifetimes tied to the dom
instead, which mostly improves performance with the
`--include-non-scripts` flag enabled
From my personal testing on an M1 mac this decreases the sourcemap
generation time of our games by 2x or more, from ~20ms to ~8ms on one
project and ~30ms to ~15ms on another. Generation is pretty fast to
begin with but since sourcemaps are heavily used in interactive tools
(like luau-lsp) a difference of a couple frames can be great for ux.
* Add user confirmation to initial sync
* Use "Accept" instead of "Confirm"
* Draw tree alphabetically for determinism
* Add diff table dropdown
* Add diff table to newly added objects
* Unblock keybind workflow
* Only show reject button when two way is enabled
* Try to patch back to the files when changes are rejected
* Improve text spacing of the prop diff table
* Skip user confirmation of perfect syncs
* Give instances names for debugging UI
* Optimize tree building
* Efficiency: dynamic virtual scrolling & lazy rendering
* Simplify virtual scroller logic and avoid wasteful rerenders
* Remove debug print
* Consistent naming
* Move new patch applied callback into accept
* Pcall archivable
* Keybinds open popup diff window
* Theme rows in diff
* Remove relic of prototype
* Color value visuals and better component name
* changeBatcher is not needed when no sync is active
* Simplify popup roact entrypoint
* Alphabetical prop lists and refactor
* Add a stroke to color blot for contrast
* Make color blots animate transparency with the rest of the page
* StyLua formatting on newly added files
* Remove wasteful table
* Fix diffing custom properties
* Display tables more meaningfully
* Allow children in the button components
* Create a rough tooltip component
* Add tooltips to buttons
* Use provider+trigger schema to avoid tooltip ZIndex issues
* Add triangle point to tooltip
* Tooltip underneath instead of covering
* Cancel hovers when unmounting
* Allow multiple canvases from one provider
* Display above or below depending on available space
* Move patch equality to PatchSet.isEqual
* Use Container
* Remove old submodules
* Reduce false positives in diff
* Add debug log
* Fuzzy equals CFrame in diffs to avoid floating point in
* Fix decodeValue usage
* Support the .changedName patches
* Fix content overlapping border
* Fix tooltip tail alignment
* Fix tooltip text fit
* Whoops, fix it properly
* Move PatchVisualizer to Components
* Provide Connected info with full patch data
* Avoid implicit nil return
* Add patch visualizer to connected page
* Make Current column invisible when visualizing applied patches
* Avoid floating point diffs in a numbers and vectors
* Add the devsetting config options into settings
* Create dropdown component and add setting controls
* Static dropdwon width and spin arrow
* Improve dropdown option contrast and border
* Forgot to make the settings page respect the static spacing, oops
* Smaller arrow
* Vert padding
* Reset option for settings
* Hide reset button when on default
* Respect the logLevel setting
* Portal settings out to external typechecking module
* Implement new configs using the new singleton Settings
* Remove DevSettings
* Update test runner to use new settings
* More helpful test failure output
* Support non-plugin environment
* Migrate dropdown to new packages system
* Clean up components a tad
* Support implicit values for primitive attributes
This commit adds support for strings, numbers, and booleans to be implicitly typed in attribute maps, reducing the redundancy of needing to specify their types.
I also quietly adjusted one of the tests to use a more stable class/property pair. Since SourceAssetId is locked to Roblox, it could potentially disappear at any time.
* Apply formatting.
* Address feedback
* Backwards compatible format usage.
* Axe UnresolvedValueMap in favor of $attributes
Attributes can be defined directly on instances, with support for unambiguous types.
* Adjust test.
* to_string() -> into()
* Made attribute test more concise.
* small cleanup
* Update src/resolution.rs
* Update src/resolution.rs
* Update src/resolution.rs
* Update src/resolution.rs
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Rough prototype of patch info display
* Remove extra newline
* Switch to binding
* Update slower for older timestamps
* Batch patches within a second of each other
* Fix indentation
* Less wasteful refresh hz
* More apt variable name
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Switch git submodules to Wally packages
* Update build snapshot
* Add wally to foreman and use latest versions
* Install packages in CI runners
* Fix indents
* Install packages in the correct directory
* Install packages in correct dir of release action too
* Remove submodules from ci checkout
* Remove submodules from release checkout
* Update selene with latest fix
* Fix whitespace
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Use singleton settings outside the Roact tree
* Cleanup listener on unmount
* Refactor setting page components
* Fix willUnmount being added to the wrong table
* Remove bindings in favor of state
* Change Notification sound to generic sound
The notification sound causes the game to summon an error due to no experience permissions with no way to grant permission. This is due to the new audio policy update.
* Update Notification sound
* Disambiguate camelCase and PascalCase.
*.meta.json forces camelCase while *.model.json forces PascalCase. This commit reinforces camelCase as the preference for both, but allows for PascalCase in both as well.
* Made requested changes, breaking due to serde bug.
* Make work with existing Serde stuff
* Work around MSRV
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Add notifications prototype
* Add timeout
* Improve function name
* Faster timeouts and fully clickable
* Update remove padding from old X button
* Only auto-dismiss when viewport is open
* Start auto dismiss once viewed
* Avoid redundantly displaying widget text as notifs
* Add sound effect
* Add setting for notifications
* Remove duplicate PluginSettings.StudioProvider
* Use short pop sound effect
* Fix broken audio, thanks Roblox
* Use e instead of createElement
* Added address reference to CLI output
* Stored loopback check address as a variable
* Changed other loopback references to the new variable
* Fixed mistake on address_string variable
* Merge write calls
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Use WeakDom::into_raw for faster snapshot generation from models
* Make compute_patch_set take snapshots by value
* Stop deferring property application in apply_patch_set
* Use InstanceBuilder::empty to avoid extra name allocations
* Git dependencies, skip dropping ServeSession
* Use std::mem::forget instead of ManuallyDrop
* Switch to latest rbx-dom crates.io dependencies
* Update other dependencies
* Port release workflow from Aftman to test
* Checkout submodules in plugin build step
* ...and build with submodules for other builds too
* Fix ci.yml; we use master branch still
* CI with submodules too
* Use session's state instead of existence to determine action
* Retain host/port text
* Use bindings instead of text/ref tunneling
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Create plugin action component
* Add plugin action for session start/end
* Add output for connection status change
* Move host & port refs to App level so keybind can access them
* Use passed function directly
* Improve the action text clarity
* Add actions for single action
* Add to changelog
* Explicitly return nil
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Change log level to info
* Refactor startSession to contain the logic
* Formatting
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Add PathNode with optional fields to project. This allows a path to be defined either as `"$path": "src"` or `"$path": { "optional": "src" }`
* Make $path truly optional
* Prevent rojo from erroring if no project node is resolved
* Use match instead of if-statement
* Add end-to-end tests (credit to MobiusCraftFlip for initial scenario)
* Pass option with ref inside instead of reference to option
* Empty commit to restart GitHub Actions
* Simplify build test
* Minimize serve test: it fails
* Simplify serve test even more
* Ignore failing serve test
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Allow for setting the default port in project json
set as
```json
"serveAddress": "0.0.0.0"
```
* Update CHANGELOG.md
* cargo fmt
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Add support for the new Open Cloud API
* Cleanup Open Cloud variables
* Avoid cloning buffer for do_upload_open_cloud
* Satisfy cargo fmt
* Actually correct cargo fmt
Apparently my earlier fix did not fix everything.
* Update CHANGELOG.md
* Update CHANGELOG.md
Forgot to add the link to issue #486 in the previous commit :/
* Cleanup & improve code for open cloud api
* Commit to force GH Actions to run (?)
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Implement ChangeBatcher
* Use ChangeBatcher for two-way sync
* Pause updates during patch application
* I can English good
* Break after encountering a nil Parent change
This prevents __flush from erroring out when an instance's Parent is
changed to nil and it has other property changes in the same batch.
* Update rbx_dom_lua
* Don't connect changed listeners in a running game
#468 made me realize how bad of an idea this is in general...
* Update TestEZ and fix sibling Ref reification test
* Add ChangeBatcher tests
* Test instance unpausing by breaking functionality out to __cycle
* Break up the module a bit and improve tests
* Shuffle requires around and edit comment
* Break out more stuff, rename createChangePatch -> createPatchSet
* Make ChangeBatcher responsible for unpausing all paused instances
This somewhat improves the situation (of course, it would preferrable
to not have to hack around this problem with Source at all). It also
sets us up nicely if we come across any other properties that do
anything similar.
* Remove old reference to pausedBatchInstances
* Use RenderStepped instead of Heartbeat and trash multi-frame pauses
I probably should have done this in the first place...
ChangeBatcher still needs to unpause instances, but we don't need to
hold pauses for any longer than one cycle.
* Remove useless branch
* if not next(x) -> if next(x) == nil
* Add InstanceMap:unpauseAllInstances, use it in ChangeBatcher
* Move IsRunning check to InstanceMap:__maybeFireInstanceChanged
* Upgrade dependencies, oneshot channel ref
* New service style?
* Fix warning
* A server is running again
* Working server with async blocks
* UI working again
* Finish upgrade
* Bump MSRV to 1.46.0 for if/match in const fn
* Update the README as part of this
* Ignore empty/whitespace-only model.json files
* Ignore no return value from model.json files during snapshot
* Use str::from_utf8 instead of String::from_utf8
* Revert "Ignore no return value from model.json files during snapshot"
This reverts commit 0aef16e30a.
* Add test for empty .model.json files
* Change empty .model.json check method
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Format code with cargo fmt
* Use raw string instead
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Ignore usage of "Name" or "Parent" in $properties
* Use match instead of array
* Add changelog entry
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* web/mod.rs - change server bind address
127.0.0.1 is a loopback interface, and only works on the same host
0.0.0.0 will allow connections from other hosts
ideally, this should be a console arg - but it's a quick fix
* implement --address option, revert default bind address to 127.0.0.1
* revert silly autoformatting
* ok, actually using rustfmt now
* More precise --address flag description
* Use SocketAddr where available, take advantage of const-ness
* Display 'localhost' if address is loopback
* Update Changelog
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Mostly mechanical port bits
* Almost there
* It builds again!
* Turn on all the code again
* Tests compiling but not passing
* Stub work for value resolution
* Implement resolution minus enums and derived properties
* Implement property descriptor resolution
* Update referent snapshots
* Update unions test project
Using a place file instead of a model yields better
error messages in Roblox Studio.
* Add easy shortcut to testing with local rbx-dom
* Update rbx-dom
* Add enum resolution
* Update init.meta.json to use UnresolvedValue
* Expand value resolution support, add test
* Filter SharedString values from web API
* Add 'property' builder method to InstanceSnapshot
* Change InstanceSnapshot/InstanceBuilder boundary
* Fix remove_file crash
* rustfmt
* Update to latest rbx_dom_lua
* Update dependencies, including rbx_dom_weak
* Update to latest rbx-dom
* Update dependencies
* Update rbx-dom, fixing more bugs
* Remove experimental warning on binary place builds
* Remove unused imports
* Add Flipper
* Remove old UI
* Add boilerplate UI
* Change plugin version
* Merge upstream
* Bunch of new UI changes
Too lazy to list them all in individual commits
* Touch ripple for buttons and a few other things
* Make the close button on the PluginGui work
* Set button state to guiEnabled
* Implement Connecting, NotConnected; add Header; don't update plugin button on render
* Replace mapLerpColor with mapLerp
* Update blendAlpha to be 0 without any values
* Add ActionFillTransparency to Theme.Button
* Suffix all Theme entries
* Update Flipper
* Add disconnect button
* Remove cancel button
* Add settings page
* Add scrollbar and dark theme support to settings
* Include settings in startSession
* Set context default value to nil
I always thought this was the name, lol...
* Add Error page
* Fix preloadAssets
* Fix preloadAssets import
* Update checkbox colors a little
* Add setting descriptions
* Fix scrolling frame in settings panel
* Remove .vscode
* Rename Throbber to Spinner
* Update merge
* Move Spinner images to assets
* Change casing of directories
* Remove old directories
* Add comments to getDerivedStateFromProps
* Account for offset in host TextBox size
* Turn width variables into constants
* Attempt to fix the comments
* Add a missing comma in Settings
* Remove a double space
* Remove Dummy object
* Move most of the Studio logic out of render
* Don't truncate port input
* Replace merge with Dictionary.merge
* Replace "Got it!" with "Okay"
* Add projectName to setStatus call
* Add Flipper to build.rs
* Start splitting apart reconciler, with tests
* Reify children in reify
* Baseline hydrate implementation
* Remove debug print
* Scaffold out diff implementation, just supporting name changes
* invariant -> error in decodeValue
* Flesh out diff and add getProperty
* Clear out top-level reconciler interface, start updating code that touches it
* Address review feedback
* Add (experimental) Selene configuration
* Add emptiness checks to PatchSet, remove unimplement invert method
* Improve descendant destruction behavior in InstanceMap
* Track instanceId on all reify errors
* Base implementation of applyPatch, returning partial patches on failure
* Change reify to accept InstanceMap and insert instances into it
* Start testing applyPatch for removals
* Add test for applyPatch adding instances successfully and not
* Add , which is just error with formatting
* Correctly use new diff and applyPatch APIs
* Improve applyPatch logging and fix field name typo
* Better debug output when reify fails
* Print out unapplied patch in debug mode
* Don't write properties if their values are not different.
This was exposed trying to sync the Rojo plugin, which
has a gigantic ModuleScript in it with the reflection
database. This workaround was present in some form in
many versions of Rojo, and I guess we still need it.
This time, I actually documented why it's here so that
I don't forget for the umpteenth time...
* Add placeholder test that needs to happen still
* Introduce easier plugin testing, write applyPatch properties test
* Delete legacy get/setCanonicalProperty files
* Fix trying to remove numbers instead of instances
* Change applyPatch to return partial patches instead of binary success
* Work towards being able to decode and apply refs
* Add helpers for PatchSet assertions
* Apply refs in reify, test all cases
* Improve diagnostics when patches fail to apply
* Stop logging when destroying untracked instances, it's ok
* Remove read before setting property in applyPatch
* Fix diff thinking all properties are changed
Fixes#320.
Previously, the root project file was loaded via methods on Project
(which do not know about the VFS) instead of through the VFS like
all other disk access.
This meant that Rojo was unable to build its own plugin because
there is no project file on the real disk, only in the VFS.
* First take at flattening middleware for simpler code and better perf
* Undo debug prints
* Fix using wrong path in snapshot_from_vfs
* Disable some broken tests
* Re-enable (mistakenly?) disabled CSV test
* Fix some tests
* Update project file tests
* Fix benchmark
* infer service names
* Update project code and add support for StarterPlayer
* Store parent_class in InstigatingSource
* Update snapshots
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* add install command
* cargo fmt
* filter spec files
* Update src/cli/plugin.rs
Co-Authored-By: Lucien Greathouse <me@lpghatguy.com>
* Update src/cli/plugin.rs
Co-Authored-By: Lucien Greathouse <me@lpghatguy.com>
* fix comments
* encode plugin with rbx_binary
* update build script
* refactor pathbuf error into io error
* fix rojo typo
* remove snafu
* Update `snapshot_from_fs_path`
* Print `rerun-if-changed` even for directories, in order to run the
build.rs script when files are added.
* Switch `filter_map` loop to a regular for loop. I like the FP-style
iterator stuff in Rust, but I think Result handling is easier in a
normal loop. Also, I don't believe the result of read_dir implements
`ExactSizedIterator`, so some of the wins of map+collect aren't there.
* Replace Result::unwrap with ? in build.rs
* Simplify error handling code in runtime
* Checkout with submodules
Co-authored-by: Lucien Greathouse <me@lpghatguy.com>
* Stub implementation
* Flesh out feature and add tests. Other snapshots currently failing.
* Blacklist .meta.json in JSON handler
* Write to correct property (Source) instead of Value
* Update changelog
- Replaced main() to use custom panic hook
- Updated log formatting
- Switched to panic=abort, since we don't need to unwind now.
- Process will now abort if any thread panics.
* vroom
* Port dir middleware
* Filter rules
* Directory metadata
* Project support
* Enable Lua support
* StringValue support
* CSV
* rbxm, rbxmx, and rbxlx
* JSON models
* Clean up some warnings
* Strip out PathMap
* Unwatch paths when they're reported as removed
* Fix 'rojo upload' behavior
* Upgrade to Insta 0.13.1
* Update dependencies
* Release 0.6.0-alpha.2
* Fix bad merge
* Replace MemoryBackend with InMemoryFs
* Sledgehammer tests into passing for now
* Txt middleware
* Update easy snapshot tests
* Lua tests
* Project middleware tests
* Try to fix test failures by sorting
* Port first set of serve session tests
* Add InMemoryFs::raise_event
* Finish porting serve session tests
* Remove UI code for introspecting VFS for now
* VFS docs
Upgrades to Roact master and introduces dynamic theme switching.
We branch on the theme name in order to try to use Rojo's brand
colors instead of Studio's. I kind of winged it with these colors
and we might want to choose slightly nicer dark theme colors
in the future.
I also took the opportunity to reorganize the color naming scheme
since it didn't really work for dark theme.
* Add Glob wrapper type with better serialization
* Introduce PathIgnoreRule struct
* Implement equality for Glob type
* Add PathIgnoreRule to InstanceContext
* Implement glob ignores in directory middleware
* Fix up filters
* Use Iterator::all instead of loop
* Add project-level configuration for glob ignores
* Add test project for glob ignores
* Wire up project file and snapshots to make glob ignores work
* Better codepaths for adding ignore rules with empty iterators
* Add test for globs inherited from parent projects
* Add test details, support glob ignores in nested projects
* Add feature flag for globs
* Switch to use ExactSizeIterator instead of size_hint
* Remove glob visitor
* Unfinished two-way sync API
* In-memory two-way sync complete
* Move PatchSet application into ChangeProcessor thread, where it can be synchronous
* Stop InstanceMap's signals when a ServeSession terminates
* Apply patch in ChangeProcessor
* Feature flag
* Fix error in ChangeProcessor due to wrong drop order
The refactor to use StructOpt instead of plain Clap had some absolute
vs relative path issues that slipped through. This commit adds getters
to each StructOpt struct that exposes an explicitly absolute version
of each path value.
* Rewrite project file to have relative paths and drop SourceProject
* Redo project error types
* Tidy up and document Project type
* Strip out init command
* Drop plugin context on the floor
* Remove redirect from old context to new context
* Pass InstanceContext via & instead of &mut reference
* Re-use context value in ChangeProcessor from metadata
This doesn't feel ideal. Though it's true that all directories are influenced by
any init scripts they have, the directory middleware shouldn't need to know
about Lua.
I don't really want to go back into working on the middleware chain since it
mostly feels like busywork when there are other things to build on in Rojo.
also all of this feels really complicated
Map sorting in Insta was previously not recursive.
As of this PR, it is!
https://github.com/mitsuhiko/insta/pull/80
Since it hasn't made it into a release yet, but is
important for Rojo to have snapshot determinism,
we're moving temporarily to depend on Insta via Git.
This was failing snapshot tests on the Linux CI machines,
since I committed snapshots with backslashes.
I think the old path serializer was still the wrong approach,
this one is sort of a middleground but I'm still not super
happy with it.
This PR refactors all of the methods on `Vfs` from accepting `&mut self` to
accepting `&self` and keeping data wrapped in a mutex. This builds on previous
changes to make reference count file contents and cleans up the last places
where we're returning borrowed data out of the VFS interface.
Once this change lands, there are two possible directions we can go that I see:
* Conservative: Refactor all remaining `&mut Vfs` handles to `&Vfs`
* Interesting: Embrace ref counting by changing `Vfs` methods to accept `self:
Arc<Self>`, which makes the `VfsEntry` API no longer need an explicit `Vfs`
argument for its operations.
* Change VfsFetcher to be immutable with internal locking
* Refactor Vfs::would_be_resident
* Refactor Vfs::read_if_not_exists
* Refactor Vfs::raise_file_removed
* Refactor Vfs::raise_file_changed
* Add Vfs::get_internal as bits of Vfs::get
* Switch Vfs to use internal locking
* Migrate all Vfs methods from &mut self to &self
* Make VfsEntry access Vfs immutably
* Remove outer VFS locking (#260)
* Refactor all snapshot middleware to accept &Vfs instead of &mut Vfs
* Remove outer VFS Mutex across the board
Initialization logic needed for serve, build, and upload is now
much more clear than it was when these functions were written.
This commit refactors all of them to use a new common_setup
module for all of their initialization that's the same.
Starts work on #55.
This is similar to the previous work in #125. It's gated behind a new Cargo
feature, `user-plugins`. This time, the config gate is much smaller. The
`plugins` member of projects is still accessible when plugins aren't enabled,
but is always empty. Additionally, user plugins are only enabled if there's a
Lua state present in the snapshot context when the `SnapshotUserPlugins`
snapshot middleware runs. This not ever the case currently.
This code has very little possibility of rotting while we focus on other work,
since it'll be guaranteed to still compile and can be tested in isolation
without the feature being turned on.
* Refactor contributing_paths into contributing_sources, deleting project node sources
* Instead of changing contributing_paths, add instigating_source
* Remove InstanceMetadata::project_node
* Stop pushing project path to front of contributing_paths since it doesn't matter now
* Remove accidental UI change for path display
* Start actually computing AppliedPatchSet values
* Improve patch_apply documentation and flesh out applied patch code
* Add file link notes
* Stub out where tests for snapshot subsystem will go
* Create baseline tests
* Fix build failure by silencing Clippy
- 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
* A minimum viable product for init.meta.json
* Properties support
* Add ignoreUnknownChildren support
* Apply requested changes
* Use reflection guiding
* Add a script to the test
* Change to ignoreUnknownInstances
* Apply requested changes
* Add children sorting to snapshot_reconciler
* Update snapshot tests to include stable children order
* Bump dependencies, which should make this PR work
- Renamed setProperty to setCanonicalProperty, which is more usefully
descriptive. Also added a detailed comment.
- Fixed reconciler behavior with regards to removing known instances
when $ignoreUnknownInstances is set
* Changes project-related structures to use `BTreeMap` instead of `HashMap` for children to aid determiniusm
* Changes imfs-related structures to have total ordering and use `BTreeSet` instead of `HashSet`
* Upgrades dependencies to `bx_dom_weak`1.2.0 and rbx_xml 0.5.0 to aid in more determinism stuff
* Re-exposes the `RbxSession`'s root project via `root_project()`
* Implements `Default` for a couple things
* Tweaks visualization code to support visualizing trees not attached to an `RbxSession`
* Adds an ID-invariant comparison method for `rbx_tree` relying on previous determinism changes
* Adds a (disabled) test to start finding issues in the reconciler with regards to communicativity of snapshot application
* Adds a snapshot testing system that operates on `RbxTree` and associated metadata, which are committed in this change
* Add 'plugins' field to project and add rlua
* Scaffold out new SnapshotContext type (again) with plugin state
* Almost functional snapshot system with rlua proof-of-concept
* Gate plugin config on 'plugins-enabled' feature, tell Travis to test all features
* Guard remaining plugin setup code behind feature
* Bump minimum version to 1.33, should've caught this before
* Whoops, latest Rust is 1.32, not 1.33
* Do the nested partition thing
* Tidy up touched code
* Add nested partition test project, not fully functional
* Clean up variable names, move path_metadata mutation strictly into snapshot_reconciler
* Remove path_metadata, snapshotting is now pure
* Factor out snapshot metadata storage to fix a missing case
* Pull instance_name out of per_path_metadata, closer to what we need
* Refactor to make metadata make more sense, part one
* All appears to be well
* Cull 'metadata_per_path' in favor of 'instances_per_path'
* Remove SnapshotContext
* InstanceMetadata -> PublicInstanceMetadata in web module
* Build in snapshot testing system for testing... snapshots?
* Remove pretty_assertions to see if it fixes a snapshot comparison bug
* Reintroduce pretty assertions, it's not the cause of inequality
* Fix snapshot tests with custom relative path serializer
* HTTP responses in the error range (400+) now properly turn into errors
* ROJO_EPIPHANY_DEV_CREATE now creates more verbose configuration
* Default configuration values are now much more explicit
* Errors that cause session termination are labeled more clearly.
* Begin the metadata merge trek
* Tidy up path metadata, entry API, begin implementing
* Flesh out use of PathMap Entry API
* Metadata per instance is a go
* Tidy up naming for metadata per instance
* SnapshotMetadata -> SnapshotContext
Permission errors aren't reported since I'm not sure what the user could do about them.
Some properties can be set in the model format but not in live-sync mode, like HttpEnabled.
This represents an evolution in how I've been thinking about Lua -- using boolean coercion
is generally a bad idea I think because it obscures the underlying types.
It also makes it so that if a boolean is eronneously passed into a function, and it
happens to be a 'false' value, it will be coerced into the nil case instead of being
reported as an error, no matter how unintuitive the resulting error might be.
I'm fairly confident that there will be zero cases where the plugin gets
into a bad state where you can't sync.
This change also prefixes most of Rojo's messages with `Rojo:` to make
them easier to identify.
Fixes#61.
* Added a setting to control patch confirmation behavior ([#774])
This is a new setting for controlling when the Rojo plugin prompts for confirmation before syncing. It has four options:
* Initial (default): prompts only once for a project in a given Studio session
* Always: always prompts for confirmation
* Large Changes: only prompts when there are more than X changed instances. The number of instances is configurable - an additional setting for the number of instances becomes available when this option is chosen
* Unlisted PlaceId: only prompts if the place ID is not present in servePlaceIds
* Added the ability to select Instances in patch visualizer ([#709])
Double-clicking an instance in the patch visualizer sets Roblox Studio's selection to the instance.
* Added a sync reminder notification. ([#689])
Rojo detects if you have previously synced to a place, and displays a notification reminding you to sync again:

* Added rich Source diffs in patch visualizer ([#748])
A "View Diff" button for script sources is now present in the patch visualizer. Clicking it displays a side-by-side diff of the script changes:


* Patch visualizer now indicates what changes failed to apply. ([#717])
A clickable warning label is displayed when the Rojo plugin is unable to apply changes. Clicking the label displays precise information about which changes failed:

#### Miscellaneous
* Added `plugin` flag to the `build` command that outputs to the local plugins folder ([#735])
This is a flag that builds a Rojo project into Roblox Studio's plugins directory. This allows you to build a Rojo project and load it into Studio as a plugin without having to type the full path to the plugins directory. It can be used like this: `rojo build <PATH-TO-PROJECT> --plugin <FILE-NAME>`
* Added new plugin template to the `init` command ([#738])
This is a new template geared towards plugins. It is similar to the model template, but creates a `Script` instead of a `ModuleScript` in the `src` directory. It can be used like this: `rojo init --kind plugin`
* Added protection against syncing non-place projects as a place. ([#691])
* Add buttons for navigation on the Connected page ([#722])
### Fixes
* Significantly improved performance of `rojo sourcemap` ([#668])
* Fixed the diff visualizer of connected sessions. ([#674])
* Fixed disconnected session activity. ([#675])
* Skip confirming patches that contain only a datamodel name change. ([#688])
* Fix Rojo breaking when users undo/redo in Studio ([#708])
* Improve tooltip behavior ([#723])
* Better settings controls ([#725])
* Rework patch visualizer with many fixes and improvements ([#713], [#726], [#755])
This is the last release candidate for Rojo 7. In an effort to get Rojo 7 out the door, we'll be freezing features from here on out, something we should've done a couple months ago.
Expect to see Rojo 7 stable soon!
* Added support for writing `Tags` in project files, model files, and meta files. ([#484])
* Adjusted Studio plugin colors to match Roblox Studio palette. ([#482])
* Improved experimental two-way sync feature by batching changes. ([#478])
This release includes a brand new implementation of the Roblox DOM. It brings performance improvements, much better support for `rbxl` and `rbxm` files, and a better internal API.
* Added support for all remaining property types.
* Added support for the entire Roblox binary model format.
* Changed `rojo upload` to upload binary places and models instead of XML.
* This should make using `rojo upload` much more feasible for large places.
* **Breaking**: Changed format of some types of values in `project.json`, `model.json`, and `meta.json` files.
* This should impact few projects. See [this file][allValues.json] for new examples of each property type.
Formatting of types will change more before the stable release of Rojo 7. We're hoping to use this opportunity to normalize some of the case inconsistency introduced in Rojo 0.5.
This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for many users for quite a long times, and so 6.0 is a more accurate reflection of Rojo's version than a pre-1.0 version.
* Added basic settings panel to plugin, with two settings:
* "Open Scripts Externally": When enabled, opening a script in Studio will instead open it in your default text editor.
* "Two-Way Sync": When enabled, Rojo will attempt to save changes to your place back to the filesystem. **Very early feature, very broken, beware!**
* Added `--color` option to force-enable or force-disable color in Rojo's output.
* Added support for turning `.json` files into `ModuleScript` instances ([#308](https://github.com/rojo-rbx/rojo/pull/308))
* Added `rojo plugin install` and `rojo plugin uninstall` to allow Rojo to manage its Roblox Studio plugin. ([#304](https://github.com/rojo-rbx/rojo/pull/304))
* Class names no longer need to be specified for Roblox services in Rojo projects. ([#210](https://github.com/rojo-rbx/rojo/pull/210))
* The server half of **experimental** two-way sync is now enabled by default.
* Increased default logging verbosity in commands like `rojo build`.
* Rojo now requires a project file again, just like 0.5.4.
* 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.
* `init.meta.json` files replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/rojo-rbx/rojo/pull/183))
* Other `.meta.json` files allow attaching extra data to other files ([#189](https://github.com/rojo-rbx/rojo/pull/189))
* Added support for infinite and NaN values in types like `Vector2` when building models and places.
* These types aren't supported for live-syncing yet due to limitations around JSON encoding.
* Added support for using `SharedString` values when building XML models and places.
* Added support for live-syncing `CollectionService` tags.
* Added a warning when building binary place files, since they're still experimental and have bugs.
* Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project.
* Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/rojo-rbx/rojo/issues/191))
* Rojo now throws an error if unknown keys are found most files.
* Added an icon to the plugin's toolbar button
* Changed the plugin to use a docking widget for all UI.
* Changed the plugin to ignore unknown properties when live-syncing.
* Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/rojo-rbx/rojo/issues/190)) or another approach.
* Upgraded to reflection database from client release 388.
* Updated Rojo's branding to shift the color palette to make it work better on dark backgrounds
* Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases.
* Building [*Road Not Taken*](https://github.com/LPGhatguy/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine
* Fixed `LocalizationTable` instances being made from `csv` files incorrectly interpreting empty rows and columns. ([#149](https://github.com/rojo-rbx/rojo/pull/149))
* Fixed CSV files with entries that parse as numbers causing Rojo to panic. ([#152](https://github.com/rojo-rbx/rojo/pull/152))
* Improved error messages when malformed CSV files are found in a Rojo project.
* Added support for a bunch of new types when dealing with XML model/place files:
* `ColorSequence`
* `Float64`
* `Int64`
* `NumberRange`
* `NumberSequence`
* `PhysicalProperties`
* `Ray`
* `Rect`
* `Ref`
* Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/rojo-rbx/rojo/pull/135))
* Fixed error being thrown when trying to unload the Rojo plugin.
* Added partial fix for [issue #141](https://github.com/rojo-rbx/rojo/issues/141) for `Lighting.Technology`, which should restore live sync functionality for the default project file.
* Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/rojo-rbx/rojo/issues/66))
* Fixed obscure error when syncing into an invalid service.
* Fixed multiple sync processes occurring when a server ID mismatch is detected.
* Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`.
* The reconciler is still not a perfect solution, especially if script instances get moved around without being destroyed. I don't think this can be fixed before a big refactor.
* Protocol version 1, which shifts more responsibility onto the server
* This is a **major breaking** change!
* The server now has a content of 'filter plugins', which transform data at various stages in the pipeline
* The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing.
* Added `*.model.json` files, which let you embed small Roblox objects into your Rojo tree.
* Improved error messages in some cases ([#46](https://github.com/rojo-rbx/rojo/issues/46))
* Factored out the plugin into a separate repository
* Fixed server when using a file as a partition
* Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory!
* Started running automatic tests on Travis CI (#9)
* Protocol version 1, which shifts more responsibility onto the server
* This is a **major breaking** change!
* The server now has a content of 'filter plugins', which transform data at various stages in the pipeline
* The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing.
* Added `*.model.json` files, which let you embed small Roblox objects into your Rojo tree.
* Improved error messages in some cases ([#46](https://github.com/LPGhatguy/rojo/issues/46))
## 0.3.2
* Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument
* Fixed intense CPU usage when running `rojo serve`
## 0.3.1
* Improved error reporting when invalid JSON is found in a `rojo.json` project
* These messages are passed on from Serde
## 0.3.0
* Factored out the plugin into a separate repository
* Fixed server when using a file as a partition
* Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory!
* Started running automatic tests on Travis CI (#9)
## 0.2.3
* Plugin only release
* Tightened `init` file rules to only match script files
* Previously, Rojo would sometimes pick up the wrong file when syncing
## 0.2.2
* Plugin only release
* Fixed broken reconciliation behavior with `init` files
## 0.2.1
* Plugin only release
* Changes default port to 8000
## 0.2.0
* Support for `init.lua` like rbxfs and rbxpacker
* More robust syncing with a new reconciler
## 0.1.0
* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs)
Rojo is a big project and can always use more help!
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 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.
## Local Development Gotchas
If your build fails with "Error: failed to open file `D:\code\rojo\plugin\modules\roact\src`" you need to update your Git submodules.
Run the command and try building again: `git submodule update --init --recursive`.
## Pushing a Rojo Release
The Rojo release process is pretty manual right now. If you need to do it, here's how:
1. Bump server version in [`Cargo.toml`](Cargo.toml)
2. Bump plugin version in [`plugin/src/Config.lua`](plugin/src/Config.lua)
3. Run `cargo test` to update `Cargo.lock` and run tests
4. Update [`CHANGELOG.md`](CHANGELOG.md)
5. Commit!
*`git add . && git commit -m "Release vX.Y.Z"`
6. Tag the commit
*`git tag vX.Y.Z`
7. Publish the CLI
*`cargo publish`
8. Publish the Plugin
*`cargo run -- upload plugin --asset_id 6415005344`
9. Push commits and tags
*`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)
This is a super rough draft that I'm trying to use to lay out some of my thoughts.
## API
### POST `/read`
Accepts a `Vec<Route>` of items to read.
Returns `Vec<Option<RbxInstance>>`, in the same order as the request.
### POST `/write`
Accepts a `Vec<{ Route, RbxInstance }>` of items to write.
I imagine that the `Name` attribute of the top-level `RbxInstance` would be ignored in favor of the route name?
## CLI
The `rojo serve` command uses three major components:
* A Virtual Filesystem (VFS), which exposes the filesystem as `VfsItem` objects
* A VFS watcher, which tracks changes to the filesystem and logs them
* An HTTP API, which exposes an interface to the Roblox Studio plugin
### Transform Plugins
Transform plugins (or filter plugins?) can interject in three places:
* Transform a `VfsItem` that's being read into an `RbxInstance` in the VFS
* Transform an `RbxInstance` that's being written into a `VfsItem` in the VFS
* Transform a file change into paths that need to be updated in the VFS watcher
The plan is to have several built-in plugins that can be rearranged/configured in project settings:
* Base plugin
* Transforms all unhandled files to/from StringValue objects
* Script plugin
* Transforms `*.lua` files to their appropriate file types
* JSON/rbxmx/rbxlx model plugin
* External binary plugin
* User passes a binary name (like `moonc`) that modifies file contents
## Roblox Studio Plugin
With the protocol version 1 change, the Roblox Studio plugin got a lot simpler. Notably, the plugin doesn't need to be aware of anything about the filesystem's semantics, which is super handy.
## Bi-directional syncing
Quenty laid out a good way to handle bi-directional syncing.
When receiving a change from the plugin:
1. Hash the new contents of the file, store it in a map from routes to hashes
2. Write the new file contents to the filesystem
3. Later down the line, receive a change event from the filesystem watcher
4. When receiving a change, if the item is in the hash map, read it and hash those contents
5. If the hash matches the last noted hash, discard the change, else continue as normal
**Rojo** is a flexible multi-tool designed for creating robust Roblox projects. It's in early development, but is still useful for many projects.
**Rojo** is a tool designed to enable Roblox developers to use professional-grade software engineering tools.
It's designed for power users who want to use the **best tools available** for building games, libraries, and plugins.
With Rojo, it's possible to use industry-leading tools like **Visual Studio Code** and **Git**.
This is the main Rojo repository, containing the binary and project server component. For the source for the Roblox plugin, [see the rojo-plugin repository](https://github.com/LPGhatguy/rojo-plugin).
The master branches of both respositories should always pass all tests and be functional, but are not suitable for production use!
Rojo is designed for power users who want to use the best tools available for building games, libraries, and plugins.
## Features
Rojo enables:
Rojo has a number of desirable features *right now*:
* Working on scripts and models from the filesystem, in your favorite editor
* Versioning your game, library, or plugin using Git or another VCS
* Streaming `rbxmx` and `rbxm` models into your game in real time
* Packaging and deploying your project to Roblox.com from the command line
* Work on scripts from the filesystem, in your favorite editor
* Version your place, library, or plugin using Git or another VCS
* Sync JSON-format models from the filesystem into your game
In the future, Rojo will be able to:
Later this year, Rojo will be able to:
* Sync instances from Roblox Studio to the filesystem
* Automatically convert your existing game to work with Rojo
* Import custom instances like MoonScript code
* Sync rbxmx-format Roblox models bi-directionally between the filesystem and Roblox Studio
* Create installation scripts for libraries to be used in standalone places
* Similar to [rbxpacker](https://github.com/LPGhatguy/rbxpacker), another one of my projects
* Add strongly-versioned dependencies to your project
## Installation
Rojo has two components:
* The command line tool, written in Rust
* The [Roblox Studio plugin](https://www.roblox.com/library/1211549683/Rojo), written in Lua
To install the command line tool, there are two options:
* Cargo, if you have Rust installed
* Use `cargo install rojo` -- Rojo will be available with the `rojo` command
* Download a pre-built Windows binary from [the GitHub releases page](https://github.com/LPGhatguy/rojo/releases)
## Usage
For more help, use `rojo help`.
### New Project
Just create a new folder and tell Rojo to initialize it!
```sh
mkdir my-new-project
cd my-new-project
rojo init
```
Rojo will create an empty project in the directory.
The default project looks like this:
```json
{
"name":"my-new-project",
"servePort":8000,
"partitions":{}
}
```
### Start Dev Server
To create a server that allows the Rojo Dev Plugin to access your project, use:
```sh
rojo serve
```
The tool will tell you whether it found an existing project. You should then be able to connect and use the project from within Roblox Studio!
### Migrating an Existing Roblox Project
**Coming soon!**
### Syncing into Roblox
In order to sync code into Roblox, you'll need to add one or more "partitions" to your configuration. A partition tells Rojo how to map directories to Roblox objects.
Each entry in the partitions table has a unique name, a filesystem path, and the full name of the Roblox object to sync into.
For example, if you want to map your `src` directory to an object named `My Cool Game` in `ReplicatedStorage`, you could use this configuration:
```json
{
"name":"rojo",
"servePort":8000,
"partitions":{
"game":{
"path":"src",
"target":"ReplicatedStorage.My Cool Game"
}
}
}
```
The `path` parameter is relative to the project file.
The `target` parameter is a path to a Roblox object to link the partition to. It starts at `game` and crawls down the tree. If any objects don't exist along the way, they'll be created as `Folder` instances.
Run `rojo serve` in the directory containing this project, then press the "Sync In" or "Toggle Polling" buttons in the Roblox Studio plugin to move code into your game.
### Sync Details
The structure of files and folders on the filesystem are preserved when syncing into game.
Creation of Roblox instances follows a simple set of rules. The first rule that matches the file name is chosen:
| `*.server.lua` | `Script` | `Source` will contain the file's contents |
| `*.client.lua` | `LocalScript` | `Source` will contain the file's contents |
| `*.lua` | `ModuleScript` | `Source` will contain the file's contents |
| `*.model.json` | *Varies* | See [this file](test-project/src/hello.model.json) for an example model |
| `*` | `StringValue` | `Value` will contain the file's contents |
Any folders on the filesystem will turn into `Folder` objects unless they contain a file named `init.lua`, `init.server.lua`, or `init.client.lua`. Following the convention of Lua, those objects will instead be whatever the `init` file would turn into.
For example, this file tree:
* my-game
* init.client.lua
* foo.lua
Will turn into this tree in Roblox:
*`my-game` (`LocalScript` with source from `my-game/init.client.lua`)
*`foo` (`ModuleScript` with source from `my-game/foo.lua`)
## Inspiration
There are lots of other tools that sync scripts into Roblox, or otherwise work to improve the development flow outside of Roblox Studio.
Here are a few, if you're looking for alternatives or supplements to Rojo:
* [Studio Bridge by Vocksel](https://github.com/vocksel/studio-bridge)
* [RbxRefresh by Osyris](https://github.com/osyrisrblx/RbxRefresh)
* [RbxSync by evaera](https://github.com/evaera/RbxSync)
* [CodeSync](https://github.com/MemoryPenguin/CodeSync) and [rbx-exteditor](https://github.com/MemoryPenguin/rbx-exteditor) by [MemoryPenguin](https://github.com/MemoryPenguin)
* [rbxmk by Anaminus](https://github.com/anaminus/rbxmk)
I also have a couple tools that Rojo intends to replace:
* [rbxfs](https://github.com/LPGhatguy/rbxfs), which has been deprecated by Rojo
* [rbxpacker](https://github.com/LPGhatguy/rbxpacker), which is still useful
## [Documentation](https://rojo.space/docs)
Documentation is hosted in the [rojo.space repository](https://github.com/rojo-rbx/rojo.space).
## Contributing
Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions for helping work on Rojo!
Pull requests are welcome!
The `master` branch of both repositories have tests running on Travis for every commit and pull request. The test suite on `master` should always pass!
The Rojo and Rojo Plugin repositories should stay in sync with eachother, so that the current `master` of each repository can be used together.
Rojo supports Rust 1.70.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has.
## License
Rojo is available under the terms of the MIT license. See [LICENSE.md](LICENSE.md) for details.
Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.