mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
139 lines
4.5 KiB
Text
139 lines
4.5 KiB
Text
---
|
|
description: "Rojo Studio plugin specifics: Roact patterns, reconciler logic, WebSocket protocol, and plugin testing."
|
|
globs:
|
|
- "plugin/**/*.lua"
|
|
- "plugin/**/*.luau"
|
|
- "plugin/**/*.json"
|
|
---
|
|
|
|
# Rojo Studio Plugin
|
|
|
|
Built with Roact (React-like), handles WebSocket sync with server, patch application to Studio, and UI.
|
|
|
|
**Entry:** `plugin/src/init.server.lua` | **Protocol:** WebSocket v5 | **Must match server MAJOR.MINOR**
|
|
|
|
## Architecture
|
|
|
|
### Key Components
|
|
|
|
**1. UI Layer** (`App/`)
|
|
- **App.lua** - Root component, manages connection state
|
|
- **Components/** - Reusable UI components
|
|
- `StatusPages/` - Connected, Connecting, Error, Settings screens
|
|
- `PatchVisualizer/` - Shows changes before applying
|
|
- `StringDiffVisualizer/` - Side-by-side script diffs
|
|
- `TableDiffVisualizer/` - Attributes and Tags diffs
|
|
- `Notifications/` - Toast notifications
|
|
- **Theme.lua** - Studio-matched color palette
|
|
- Uses Roact for declarative UI
|
|
|
|
**2. Communication** (`ServeSession.lua`)
|
|
- WebSocket connection to server (previously long-polling)
|
|
- Handles patches, errors, reconnection
|
|
- Protocol version checking
|
|
|
|
**3. Reconciler** (`Reconciler/`)
|
|
- **applyPatch.lua** - Applies server patches to Studio tree
|
|
- **reify.lua** - Creates instances from snapshots
|
|
- **hydrate.lua** - Updates existing instances
|
|
- **diff.lua** - Generates patches (for two-way sync)
|
|
- **decodeValue.lua** - Converts encoded values to Roblox types
|
|
- **setProperty.lua** - Sets properties safely
|
|
- **getProperty.lua** - Gets properties with fallbacks
|
|
|
|
**4. State Management**
|
|
- **Settings.lua** - Persistent plugin settings
|
|
- **InstanceMap.lua** - Tracks server ID → Studio instance mapping
|
|
- **PatchSet.lua** / **PatchTree.lua** - Patch representation
|
|
|
|
**5. Testing**
|
|
- Unit tests: `.spec.lua` files (TestEZ)
|
|
- Integration tests: `integration/` directory
|
|
- Stress tests: `.stress.spec.lua` files
|
|
- Test runner: `runTests.lua`
|
|
|
|
## Key Configuration (`Config.lua`)
|
|
|
|
```lua
|
|
{
|
|
version = {7, 7, 0, "-rc.1"},
|
|
protocolVersion = 5, -- MUST match server
|
|
ignoredClassNames = { TouchTransmitter = true, Camera = true }
|
|
}
|
|
```
|
|
|
|
**When changing protocol:** Bump `protocolVersion` in both plugin AND server.
|
|
|
|
## WebSocket Protocol (v5)
|
|
|
|
1. Connect to `ws://host:port/api/rojo`
|
|
2. Server sends: protocol version, project name
|
|
3. Plugin sends: `{"type": "Subscribe"}`
|
|
4. Server sends patches on filesystem changes
|
|
|
|
**Patch structure:**
|
|
```lua
|
|
{
|
|
type = "ApplyPatch",
|
|
sessionId = "uuid",
|
|
patch = {
|
|
removed = {"id1", "id2"}, -- Array of IDs (Vec<Ref>)
|
|
added = { ["id3"] = {...} }, -- Map: ID → Instance data
|
|
updated = { -- Array of updates (Vec<InstanceUpdate>)
|
|
{ id = "id4", changedName = "...", changedProperties = {...} }
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Reconciler (`Reconciler/`)
|
|
|
|
**applyPatch.lua** - Main patch application:
|
|
1. Remove instances in `removed`
|
|
2. Create instances in `added` via `reify`
|
|
3. Update instances in `updated` via `hydrate`
|
|
4. Collect errors, show in UI
|
|
|
|
**reify.lua** - Create instances (parent last - Roblox best practice)
|
|
**hydrate.lua** - Update existing (only changed properties)
|
|
**setProperty.lua** / **getProperty.lua** - Handle unscriptable properties
|
|
|
|
## UI Components (`App/`)
|
|
|
|
**StatusPages:** NotConnected, Connecting, Connected, Error, Settings
|
|
**PatchVisualizer:** Tree view of changes with property diffs
|
|
**StringDiffVisualizer:** Side-by-side script diffs
|
|
**TableDiffVisualizer:** Attributes and Tags diffs
|
|
**Notifications:** Toast messages
|
|
**Theme.lua:** Studio-matched colors (auto light/dark)
|
|
|
|
## InstanceMap
|
|
|
|
Bidirectional Server ID ↔ Studio Instance mapping:
|
|
|
|
```lua
|
|
instanceMap:insert(serverId, studioInstance)
|
|
local instance = instanceMap:fromId(serverId)
|
|
local serverId = instanceMap:fromInstance(instance)
|
|
```
|
|
|
|
Critical for patch application and avoiding duplicates.
|
|
|
|
## Two-Way Sync (Experimental)
|
|
|
|
⚠️ Watches Studio changes, sends to server. Has known issues - use with caution.
|
|
|
|
## Dependencies (`plugin/Packages/`)
|
|
|
|
Roact, Flipper, Promise, TestEZ, t, Highlighter, msgpack-luau. **Don't edit vendored packages.**
|
|
|
|
## Common Issues
|
|
|
|
**Plugin not reloading:** Enable Studio setting "Reload plugins on file change"
|
|
**Connection fails:** Check server running, host/port match, protocol versions match
|
|
**Properties not syncing:** Verify scriptable in rbx_reflection_database
|
|
**Duplicates:** InstanceMap corruption - disconnect, restart Studio
|
|
|
|
## Debugging
|
|
|
|
Settings → Log Level → "Trace" for verbose output. `ROJO_DEV_BUILD` instance enables auto-tests.
|