mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
Update references to UserGeneratedLLC in documentation and enhance project file specifications
- Changed all instances of `rojo-rbx` to `UserGeneratedLLC` in the rbx-dom and rojo documentation to reflect the new repository ownership. - Updated project file format specifications to prioritize `.project.json5` over `.project.json`, clarifying the preferred file extensions and their usage. - Revised syncback documentation to reflect changes in file extensions from `.lua` to `.luau`, ensuring consistency across the project. - Improved clarity in the API and communication architecture documentation, emphasizing the new structure and endpoints.
This commit is contained in:
parent
e6efc04756
commit
1bf32f0920
6 changed files with 782 additions and 1264 deletions
|
|
@ -8,7 +8,7 @@ globs:
|
||||||
|
|
||||||
# rbx-dom Submodule
|
# rbx-dom Submodule
|
||||||
|
|
||||||
**This is a Git submodule** linking to https://github.com/rojo-rbx/rbx-dom - a separate project with its own repository, CI/CD, and release cycle.
|
**This is a Git submodule** linking to https://github.com/UserGeneratedLLC/rbx-dom - a separate project with its own repository, CI/CD, and release cycle.
|
||||||
|
|
||||||
**Critical:** When working on rbx-dom code, refer to `rbx-dom/README.md` and follow that project's conventions, not Rojo's.
|
**Critical:** When working on rbx-dom code, refer to `rbx-dom/README.md` and follow that project's conventions, not Rojo's.
|
||||||
|
|
||||||
|
|
@ -65,7 +65,7 @@ A collection of cross-platform libraries enabling any software to interact with
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clone Rojo with submodules
|
# Clone Rojo with submodules
|
||||||
git clone --recursive https://github.com/rojo-rbx/rojo
|
git clone --recursive https://github.com/UserGeneratedLLC/rojo
|
||||||
|
|
||||||
# Or update existing submodules
|
# Or update existing submodules
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
@ -105,7 +105,7 @@ Since rbx-dom is a separate repository:
|
||||||
|
|
||||||
1. **Fork and clone rbx-dom separately** for development
|
1. **Fork and clone rbx-dom separately** for development
|
||||||
2. **Make changes in the rbx-dom repository** (not the submodule)
|
2. **Make changes in the rbx-dom repository** (not the submodule)
|
||||||
3. **Open PRs against rojo-rbx/rbx-dom** (not rojo-rbx/rojo)
|
3. **Open PRs against UserGeneratedLLC/rbx-dom** (not UserGeneratedLLC/rojo)
|
||||||
4. **Update Rojo's submodule** only after rbx-dom changes are merged
|
4. **Update Rojo's submodule** only after rbx-dom changes are merged
|
||||||
|
|
||||||
### Testing Changes
|
### Testing Changes
|
||||||
|
|
@ -152,7 +152,7 @@ rbx-dom packages must be published **in dependency order**:
|
||||||
4. `rbx_binary` and `rbx_xml` (depend on all above)
|
4. `rbx_binary` and `rbx_xml` (depend on all above)
|
||||||
|
|
||||||
**Only maintainers can publish.** If you need a new rbx-dom release:
|
**Only maintainers can publish.** If you need a new rbx-dom release:
|
||||||
1. Open issue in rojo-rbx/rbx-dom
|
1. Open issue in UserGeneratedLLC/rbx-dom
|
||||||
2. Explain what features/fixes you need
|
2. Explain what features/fixes you need
|
||||||
3. Maintainers will coordinate release
|
3. Maintainers will coordinate release
|
||||||
|
|
||||||
|
|
@ -168,10 +168,10 @@ git submodule update --init --recursive
|
||||||
cd rbx-dom && git checkout main && git pull
|
cd rbx-dom && git checkout main && git pull
|
||||||
```
|
```
|
||||||
|
|
||||||
**Property bugs:** Check `rbx-dom/test-files/` for similar cases, file issue in rojo-rbx/rbx-dom
|
**Property bugs:** Check `rbx-dom/test-files/` for similar cases, file issue in UserGeneratedLLC/rbx-dom
|
||||||
|
|
||||||
**Outdated reflection:** File issue requesting reflection database update (maintainers run `rbx_reflector`)
|
**Outdated reflection:** File issue requesting reflection database update (maintainers run `rbx_reflector`)
|
||||||
|
|
||||||
## Contributing to rbx-dom
|
## Contributing to rbx-dom
|
||||||
|
|
||||||
See https://github.com/rojo-rbx/rbx-dom. Remember: rbx-dom is designed for projects beyond Rojo, so changes should be general-purpose.
|
See https://github.com/UserGeneratedLLC/rbx-dom. Remember: rbx-dom is designed for projects beyond Rojo, so changes should be general-purpose.
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,312 +1,250 @@
|
||||||
---
|
---
|
||||||
description: "Project file format specification: .project.json schema, all file extensions, middleware types, init files, sync rules, and complete property reference."
|
description: "Project file format specification: .project.json5 schema, file extensions, middleware types, init files, sync rules, and property reference."
|
||||||
globs:
|
globs:
|
||||||
- "**/*.project.json"
|
|
||||||
- "**/*.project.json5"
|
- "**/*.project.json5"
|
||||||
- "**/*.meta.json"
|
- "**/*.project.json"
|
||||||
- "**/*.meta.json5"
|
- "**/*.meta.json5"
|
||||||
- "**/*.model.json"
|
- "**/*.meta.json"
|
||||||
- "**/*.model.json5"
|
- "**/*.model.json5"
|
||||||
|
- "**/*.model.json"
|
||||||
---
|
---
|
||||||
|
|
||||||
# Rojo Project File Format Specification
|
# Rojo Project File Format
|
||||||
|
|
||||||
Complete reference for Rojo project files, file type mappings, and middleware system.
|
|
||||||
|
|
||||||
## Project File Schema
|
## Project File Schema
|
||||||
|
|
||||||
### File Names
|
**Recognized files:** `*.project.json5` (preferred) | `*.project.json` (legacy)
|
||||||
|
|
||||||
**Recognized project files (in priority order):**
|
**Special:** `default.project.json5` inherits parent folder name.
|
||||||
1. `*.project.json5` - Preferred (supports comments, trailing commas)
|
|
||||||
2. `*.project.json` - Legacy (strict JSON)
|
|
||||||
|
|
||||||
**Special names:**
|
| Field | Type | Required | Description |
|
||||||
- `default.project.json5` - Instance inherits parent folder name
|
|-------|------|----------|-------------|
|
||||||
- `default.project.json` - Legacy equivalent
|
| `name` | string | Yes* | Instance name (*optional if `default.project.json5`) |
|
||||||
- `MyGame.project.json5` - Instance named "MyGame"
|
| `tree` | ProjectNode | Yes | Root instance tree structure |
|
||||||
|
| `servePort` | number | No | Port for `rojo serve` (default: 34872) |
|
||||||
### Root Schema
|
| `serveAddress` | string | No | Address to bind (default: `"127.0.0.1"`) |
|
||||||
|
| `servePlaceIds` | number[] | No | Only allow sync to these place IDs |
|
||||||
|
| `blockedPlaceIds` | number[] | No | Block sync to these place IDs |
|
||||||
|
| `placeId` | number | No | Set place ID on plugin connect |
|
||||||
|
| `gameId` | number | No | Set game/universe ID on plugin connect |
|
||||||
|
| `globIgnorePaths` | string[] | No | Glob patterns to ignore during sync |
|
||||||
|
| `syncRules` | SyncRule[] | No | Custom file type mappings |
|
||||||
|
| `syncbackRules` | SyncbackRules | No | Syncback configuration |
|
||||||
|
| `syncScriptsOnly` | bool | No | Only sync script instances (default: false) |
|
||||||
|
| `ignoreHiddenServices` | bool | No | Ignore internal services (default: true) |
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
// Optional: JSON Schema reference
|
"$schema": "https://raw.githubusercontent.com/UserGeneratedLLC/vscode-rojo/master/schemas/project.schema.json",
|
||||||
"$schema": "https://raw.githubusercontent.com/rojo-rbx/vscode-rojo/master/schemas/project.schema.json",
|
|
||||||
|
|
||||||
// REQUIRED: Instance name (optional if default.project.json)
|
|
||||||
"name": "MyProject",
|
"name": "MyProject",
|
||||||
|
"tree": { /* ProjectNode */ },
|
||||||
// REQUIRED: Instance tree structure
|
|
||||||
"tree": {
|
|
||||||
// See ProjectNode schema below
|
|
||||||
},
|
|
||||||
|
|
||||||
// Optional: Default port for `rojo serve`
|
|
||||||
"servePort": 34872,
|
"servePort": 34872,
|
||||||
|
"serveAddress": "0.0.0.0",
|
||||||
// Optional: Allowed place IDs for live sync
|
"servePlaceIds": [123456],
|
||||||
"servePlaceIds": [123456, 789012],
|
|
||||||
|
|
||||||
// Optional: Blocked place IDs (cannot sync to these)
|
|
||||||
"blockedPlaceIds": [111111],
|
"blockedPlaceIds": [111111],
|
||||||
|
|
||||||
// Optional: Set place ID on connect
|
|
||||||
"placeId": 123456,
|
"placeId": 123456,
|
||||||
|
|
||||||
// Optional: Set game ID on connect
|
|
||||||
"gameId": 789012,
|
"gameId": 789012,
|
||||||
|
"globIgnorePaths": ["**/*.md", "**/node_modules/**"],
|
||||||
// Optional: Default address for `rojo serve`
|
"syncRules": [/* SyncRule */],
|
||||||
"serveAddress": "0.0.0.0", // or "127.0.0.1", etc.
|
"syncbackRules": { /* SyncbackRules */ },
|
||||||
|
|
||||||
// Optional: Glob patterns to ignore
|
|
||||||
"globIgnorePaths": [
|
|
||||||
"**/*.md",
|
|
||||||
"**/.git/**",
|
|
||||||
"**/node_modules/**"
|
|
||||||
],
|
|
||||||
|
|
||||||
// Optional: Custom file type mappings
|
|
||||||
"syncRules": [
|
|
||||||
{
|
|
||||||
"pattern": "*.foo",
|
|
||||||
"use": "text",
|
|
||||||
"suffix": ".foo",
|
|
||||||
"exclude": "*.test.foo"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
|
|
||||||
// Optional: Syncback configuration
|
|
||||||
"syncbackRules": {
|
|
||||||
"ignoreTrees": ["ServerStorage/Secrets"],
|
|
||||||
"ignorePaths": ["src/client/*"],
|
|
||||||
"ignoreProperties": {
|
|
||||||
"BasePart": ["Color"]
|
|
||||||
},
|
|
||||||
"syncCurrentCamera": false,
|
|
||||||
"syncUnscriptable": true
|
|
||||||
},
|
|
||||||
|
|
||||||
// Optional: Only sync script instances (default: false)
|
|
||||||
"syncScriptsOnly": false,
|
"syncScriptsOnly": false,
|
||||||
|
|
||||||
// Optional: Ignore hidden services (default: true)
|
|
||||||
"ignoreHiddenServices": true
|
"ignoreHiddenServices": true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## ProjectNode Schema
|
## ProjectNode Schema
|
||||||
|
|
||||||
**Used in `tree` field and recursively for children.**
|
Used in `tree` and recursively for all children.
|
||||||
|
|
||||||
|
| Field | Type | Description |
|
||||||
|
|-------|------|-------------|
|
||||||
|
| `$className` | string | Instance class (required for non-services) |
|
||||||
|
| `$path` | string | Filesystem path to sync from |
|
||||||
|
| `$id` | string | Unique ID for Ref property linking |
|
||||||
|
| `$properties` | object | Instance properties to set |
|
||||||
|
| `$attributes` | object | Instance attributes to set |
|
||||||
|
| `$ignoreUnknownInstances` | bool | Whether to ignore instances not in project during sync |
|
||||||
|
|
||||||
|
**Keys without `$` prefix are child instances.**
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
// Optional: Instance class (inferred for services, required for others)
|
|
||||||
"$className": "Folder",
|
"$className": "Folder",
|
||||||
|
|
||||||
// Optional: ID for Ref property linking
|
|
||||||
"$id": "unique-identifier",
|
|
||||||
|
|
||||||
// Optional: Path to filesystem
|
|
||||||
"$path": "src/MyFolder",
|
"$path": "src/MyFolder",
|
||||||
|
"$id": "unique-id",
|
||||||
// Optional: Instance properties
|
"$properties": { "Anchored": true },
|
||||||
"$properties": {
|
"$attributes": { "Health": 100 },
|
||||||
"Anchored": true,
|
|
||||||
"Position": [0, 5, 0], // Shorthand Vector3
|
|
||||||
"BrickColor": "Bright red",
|
|
||||||
"Size": { // Explicit type
|
|
||||||
"Vector3": [4, 1, 2]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Optional: Instance attributes
|
|
||||||
"$attributes": {
|
|
||||||
"Health": 100,
|
|
||||||
"MaxSpeed": 16.5,
|
|
||||||
"IsEnemy": false
|
|
||||||
},
|
|
||||||
|
|
||||||
// Optional: Ignore unknown instances during sync (default: varies)
|
|
||||||
"$ignoreUnknownInstances": false,
|
"$ignoreUnknownInstances": false,
|
||||||
|
|
||||||
// Children (no $ prefix = child instances)
|
// Children
|
||||||
"ChildFolder": {
|
"ChildFolder": { "$className": "Folder" },
|
||||||
"$className": "Folder"
|
"MyScript": { "$path": "src/MyScript.luau" }
|
||||||
},
|
|
||||||
|
|
||||||
"MyScript": {
|
|
||||||
"$path": "src/MyScript.lua"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Reserved Names
|
**Services auto-inferred:** Workspace, ReplicatedStorage, ServerScriptService, ServerStorage, StarterGui, StarterPlayer, Lighting, Teams, Chat, SoundService, LocalizationService, TestService, etc.
|
||||||
|
|
||||||
**ALL keys starting with `$` are reserved:**
|
|
||||||
- `$className` - Instance class
|
|
||||||
- `$path` - Filesystem path
|
|
||||||
- `$properties` - Instance properties
|
|
||||||
- `$attributes` - Instance attributes
|
|
||||||
- `$id` - Ref linking ID
|
|
||||||
- `$ignoreUnknownInstances` - Sync behavior
|
|
||||||
- `$keepUnknownInstances` - Legacy (use `$ignoreUnknownInstances`)
|
|
||||||
|
|
||||||
**Keys WITHOUT `$` are children.**
|
|
||||||
|
|
||||||
## File Extension Mappings
|
## File Extension Mappings
|
||||||
|
|
||||||
### Script Files
|
### Scripts
|
||||||
|
|
||||||
| Extension | Middleware | Result | RunContext |
|
| Extension | Result | RunContext | Note |
|
||||||
|-----------|-----------|--------|------------|
|
|-----------|--------|------------|------|
|
||||||
| `*.lua` | `Lua` | ModuleScript | N/A |
|
| `*.luau` | ModuleScript | — | Preferred |
|
||||||
| `*.luau` | `Lua` | ModuleScript | N/A |
|
| `*.server.luau` | Script | Server | Preferred |
|
||||||
| `*.server.luau` | `ServerScript` | Script | Server |
|
| `*.client.luau` | Script | Client | Preferred |
|
||||||
| `*.server.lua` | `ServerScript` | Script | Legacy |
|
| `*.plugin.luau` | Script | Plugin | |
|
||||||
| `*.client.luau` | `ClientScript` | Script | Client |
|
| `*.local.luau` | LocalScript | — | |
|
||||||
| `*.client.lua` | `ClientScript` | LocalScript | N/A |
|
| `*.legacy.luau` | Script | Legacy | |
|
||||||
| `*.plugin.lua` | `PluginScript` | Script | Plugin |
|
| `*.lua` | ModuleScript | — | Legacy |
|
||||||
| `*.plugin.luau` | `PluginScript` | Script | Plugin |
|
| `*.server.lua` | Script | Legacy | Legacy |
|
||||||
| `*.local.lua` | `LocalScript` | LocalScript | N/A |
|
| `*.client.lua` | LocalScript | — | Legacy |
|
||||||
| `*.local.luau` | `LocalScript` | LocalScript | N/A |
|
|
||||||
| `*.legacy.lua` | `LegacyScript` | Script | Legacy |
|
|
||||||
| `*.legacy.luau` | `LegacyScript` | Script | Legacy |
|
|
||||||
|
|
||||||
**Note:** `.lua` and `.luau` extensions produce different results for server/client scripts:
|
**Prefer `.luau`** — modern RunContext. `.lua` is legacy (still supported).
|
||||||
- `.server.luau` → Script with RunContext.Server (modern)
|
|
||||||
- `.server.lua` → Script with RunContext.Legacy (backwards compat)
|
|
||||||
- `.client.luau` → Script with RunContext.Client (modern)
|
|
||||||
- `.client.lua` → LocalScript (backwards compat)
|
|
||||||
|
|
||||||
### Model Files
|
### Models & Data
|
||||||
|
|
||||||
| Extension | Middleware | Format | Use Case |
|
| Extension | Result | Note |
|
||||||
|-----------|-----------|--------|----------|
|
|-----------|--------|------|
|
||||||
| `*.rbxm` | `Rbxm` | Binary | Production models |
|
| `*.rbxm` | Binary model | |
|
||||||
| `*.rbxmx` | `Rbxmx` | XML | Debugging, diffs |
|
| `*.rbxmx` | XML model | |
|
||||||
| `*.model.json` | `JsonModel` | JSON | Simple instances |
|
| `*.model.json5` | JSON model | Preferred |
|
||||||
| `*.model.json5` | `JsonModel` | JSON5 | Simple instances (comments) |
|
| `*.model.json` | JSON model | Legacy |
|
||||||
|
| `*.txt` | StringValue | |
|
||||||
|
| `*.csv` | LocalizationTable | |
|
||||||
|
| `*.json5` | ModuleScript (Lua table) | Preferred |
|
||||||
|
| `*.json` | ModuleScript (Lua table) | Legacy |
|
||||||
|
| `*.toml` | ModuleScript (Lua table) | |
|
||||||
|
| `*.yaml`, `*.yml` | ModuleScript (Lua table) | |
|
||||||
|
|
||||||
### Data Files
|
### Meta & Project
|
||||||
|
|
||||||
| Extension | Middleware | Result | Content |
|
| Extension | Purpose | Note |
|
||||||
|-----------|-----------|--------|---------|
|
|-----------|---------|------|
|
||||||
| `*.txt` | `Txt` | StringValue | File contents → `Value` |
|
| `*.meta.json5` | Add properties/attributes to sibling | Preferred |
|
||||||
| `*.csv` | `Csv` | LocalizationTable | CSV → localization data |
|
| `*.meta.json` | Add properties/attributes to sibling | Legacy |
|
||||||
| `*.toml` | `Toml` | ModuleScript | TOML → Lua table |
|
| `*.project.json5` | Nested project | Preferred |
|
||||||
| `*.json` | `Json` | ModuleScript | JSON → Lua table |
|
| `*.project.json` | Nested project | Legacy |
|
||||||
| `*.json5` | `Json` | ModuleScript | JSON5 → Lua table |
|
|
||||||
| `*.yaml` | `Yaml` | ModuleScript | YAML → Lua table |
|
|
||||||
| `*.yml` | `Yaml` | ModuleScript | YAML → Lua table |
|
|
||||||
|
|
||||||
### Meta Files
|
## Init File Priority
|
||||||
|
|
||||||
| Extension | Purpose | Example |
|
When directory has multiple init files, first match wins:
|
||||||
|-----------|---------|---------|
|
|
||||||
| `*.meta.json` | Add metadata | `MyScript.meta.json` |
|
|
||||||
| `*.meta.json5` | Add metadata | `MyScript.meta.json5` |
|
|
||||||
|
|
||||||
**Meta files add:**
|
1. `default.project.json5` → Nested project (preferred)
|
||||||
- Properties
|
|
||||||
- Attributes
|
|
||||||
- ClassName override
|
|
||||||
|
|
||||||
### Project Files
|
|
||||||
|
|
||||||
| Extension | Purpose |
|
|
||||||
|-----------|---------|
|
|
||||||
| `*.project.json` | Nested project (strict JSON) |
|
|
||||||
| `*.project.json5` | Nested project (preferred) |
|
|
||||||
|
|
||||||
**Special:** `default.project.json5` in directory acts as init file.
|
|
||||||
|
|
||||||
## Init Files
|
|
||||||
|
|
||||||
**Init files** name instance after parent directory, enabling nested structures.
|
|
||||||
|
|
||||||
### Priority Order
|
|
||||||
|
|
||||||
**When directory has multiple init files, Rojo uses first match:**
|
|
||||||
|
|
||||||
1. `default.project.json5` → Nested project (CHECKED FIRST)
|
|
||||||
2. `default.project.json` → Nested project (legacy)
|
2. `default.project.json` → Nested project (legacy)
|
||||||
3. `init.luau` → ModuleScript
|
3. `init.luau` → ModuleScript (preferred)
|
||||||
4. `init.server.luau` → Script (RunContext.Server)
|
4. `init.server.luau` → Script (Server)
|
||||||
5. `init.client.luau` → Script (RunContext.Client)
|
5. `init.client.luau` → Script (Client)
|
||||||
6. `init.plugin.luau` → Script (RunContext.Plugin)
|
6. `init.plugin.luau` → Script (Plugin)
|
||||||
7. `init.local.luau` → LocalScript
|
7. `init.local.luau` → LocalScript
|
||||||
8. `init.legacy.luau` → Script (RunContext.Legacy)
|
8. `init.legacy.luau` → Script (Legacy)
|
||||||
9. `init.csv` → LocalizationTable
|
9. `init.csv` → LocalizationTable
|
||||||
10. `init.lua` → ModuleScript
|
10. `init.lua` → ModuleScript (legacy)
|
||||||
11. `init.server.lua` → Script (RunContext.Legacy)
|
11. `init.server.lua` → Script (Legacy)
|
||||||
12. `init.client.lua` → LocalScript
|
12. `init.client.lua` → LocalScript (legacy)
|
||||||
|
|
||||||
**No init file?** → Directory becomes Folder (or inferred service).
|
**No init file?** → Directory becomes Folder. **Prefer `.luau` and `.json5` extensions.**
|
||||||
|
|
||||||
**Important:** Project files take highest priority. Legacy `.lua` extensions produce different script types than modern `.luau`.
|
## Sync Rules Schema
|
||||||
|
|
||||||
### Example: Init File Structure
|
Custom file type handling in `syncRules` array:
|
||||||
|
|
||||||
```
|
| Field | Type | Required | Description |
|
||||||
MyModule/
|
|-------|------|----------|-------------|
|
||||||
init.luau ← ModuleScript named "MyModule"
|
| `pattern` | string | Yes | Glob pattern to match files |
|
||||||
types.luau ← Child ModuleScript "types"
|
| `use` | string | Yes | Middleware type (see table below) |
|
||||||
utils.luau ← Child ModuleScript "utils"
|
| `suffix` | string | No | Extension to strip from instance name |
|
||||||
```
|
| `exclude` | string | No | Glob pattern to exclude from matching |
|
||||||
|
|
||||||
**Equivalent to:**
|
|
||||||
```
|
|
||||||
ModuleScript "MyModule"
|
|
||||||
├─ ModuleScript "types"
|
|
||||||
└─ ModuleScript "utils"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Service Inference
|
|
||||||
|
|
||||||
**Services don't require `$className`:**
|
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
"name": "MyGame",
|
"syncRules": [{
|
||||||
"tree": {
|
"pattern": "*.foo",
|
||||||
// Inferred as Workspace service
|
"use": "moduleScript",
|
||||||
"Workspace": {
|
"suffix": ".foo",
|
||||||
"$path": "src/workspace"
|
"exclude": "*.test.foo"
|
||||||
},
|
}]
|
||||||
|
|
||||||
// Inferred as ServerScriptService
|
|
||||||
"ServerScriptService": {
|
|
||||||
"$path": "src/server"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Must specify (not a service)
|
|
||||||
"MyFolder": {
|
|
||||||
"$className": "Folder",
|
|
||||||
"$path": "src/modules"
|
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `use` Values
|
||||||
|
|
||||||
|
| Value | Result |
|
||||||
|
|-------|--------|
|
||||||
|
| `serverScript` | Script (Server) |
|
||||||
|
| `clientScript` | Script (Client) |
|
||||||
|
| `moduleScript` | ModuleScript |
|
||||||
|
| `pluginScript` | Script (Plugin) |
|
||||||
|
| `localScript` | LocalScript |
|
||||||
|
| `legacyScript` | Script (Legacy) |
|
||||||
|
| `json`, `toml`, `yaml` | ModuleScript |
|
||||||
|
| `csv` | LocalizationTable |
|
||||||
|
| `text` | StringValue |
|
||||||
|
| `jsonModel`, `rbxm`, `rbxmx` | Instance tree |
|
||||||
|
| `project` | Nested project |
|
||||||
|
| `ignore` | Skip file |
|
||||||
|
|
||||||
|
## Syncback Rules Schema
|
||||||
|
|
||||||
|
Configure `syncbackRules` object for Roblox → filesystem sync:
|
||||||
|
|
||||||
|
| Field | Type | Default | Description |
|
||||||
|
|-------|------|---------|-------------|
|
||||||
|
| `ignoreTrees` | string[] | `[]` | Roblox tree paths to skip (e.g., `"ServerStorage/Secrets"`) |
|
||||||
|
| `ignorePaths` | string[] | `[]` | Filesystem glob patterns to skip (e.g., `"src/generated/*"`) |
|
||||||
|
| `ignoreProperties` | object | `{}` | Properties to skip per class: `{"ClassName": ["Prop1", "Prop2"]}` |
|
||||||
|
| `ignoreClasses` | string[] | `[]` | Instance classes to skip entirely |
|
||||||
|
| `syncCurrentCamera` | bool | `false` | Whether to sync `Workspace.CurrentCamera` |
|
||||||
|
| `syncUnscriptable` | bool | `true` | Whether to sync unscriptable properties |
|
||||||
|
| `ignoreReferents` | bool | `false` | Whether to skip Ref properties (e.g., `Model.PrimaryPart`) |
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
"syncbackRules": {
|
||||||
|
"ignoreTrees": ["ServerStorage/Secrets", "Workspace/Camera"],
|
||||||
|
"ignorePaths": ["src/generated/*", "src/temp/**"],
|
||||||
|
"ignoreProperties": {
|
||||||
|
"BasePart": ["Color", "BrickColor"],
|
||||||
|
"Script": ["Disabled"]
|
||||||
|
},
|
||||||
|
"ignoreClasses": ["Terrain", "Camera"],
|
||||||
|
"syncCurrentCamera": false,
|
||||||
|
"syncUnscriptable": true,
|
||||||
|
"ignoreReferents": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Recognized services:**
|
## Meta Files
|
||||||
- Workspace
|
|
||||||
- Lighting
|
|
||||||
- ReplicatedFirst
|
|
||||||
- ReplicatedStorage
|
|
||||||
- ServerScriptService
|
|
||||||
- ServerStorage
|
|
||||||
- StarterGui
|
|
||||||
- StarterPack
|
|
||||||
- StarterPlayer
|
|
||||||
- Teams
|
|
||||||
- SoundService
|
|
||||||
- Chat
|
|
||||||
- LocalizationService
|
|
||||||
- TestService
|
|
||||||
- And all other DataModel services
|
|
||||||
|
|
||||||
**Special:** `Terrain` is also inferred.
|
Add metadata to file-based instances. Example: `MyScript.server.meta.json5` (for `MyScript.server.luau`)
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
"$className": "Script", // Override (rare)
|
||||||
|
"$properties": { "Disabled": false },
|
||||||
|
"$attributes": { "Priority": 1 },
|
||||||
|
"$ignoreUnknownInstances": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Meta files CAN'T:** Override name, set `$path`, have children.
|
||||||
|
|
||||||
|
## Model.json5 Format
|
||||||
|
|
||||||
|
Inline instance definition:
|
||||||
|
|
||||||
|
```json5
|
||||||
|
{
|
||||||
|
"$className": "Tool",
|
||||||
|
"$properties": { "CanBeDropped": false },
|
||||||
|
"$attributes": { "Damage": 50 },
|
||||||
|
"Handle": {
|
||||||
|
"$className": "Part",
|
||||||
|
"$properties": { "Size": [1, 1, 3] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Property Formats
|
## Property Formats
|
||||||
|
|
||||||
|
|
@ -315,145 +253,59 @@ ModuleScript "MyModule"
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
"$properties": {
|
"$properties": {
|
||||||
// Primitives
|
"Anchored": true, // Bool
|
||||||
"Anchored": true,
|
"Health": 100, // Number
|
||||||
"Disabled": false,
|
|
||||||
"Name": "MyPart", // Warning: Don't set Name in properties!
|
|
||||||
|
|
||||||
// Numbers
|
|
||||||
"Health": 100,
|
|
||||||
"Speed": 16.5,
|
|
||||||
|
|
||||||
// Strings
|
|
||||||
"Source": "print('hello')",
|
|
||||||
|
|
||||||
// Vector types (arrays)
|
|
||||||
"Position": [0, 5, 0], // Vector3
|
"Position": [0, 5, 0], // Vector3
|
||||||
"Size": [4, 1, 2], // Vector3
|
|
||||||
"Velocity": [1, 0, 0], // Vector3
|
|
||||||
"ImageRectSize": [100, 100], // Vector2
|
"ImageRectSize": [100, 100], // Vector2
|
||||||
|
"Color": [1, 0, 0], // Color3 (normalized RGB)
|
||||||
// Color3 (normalized RGB)
|
|
||||||
"Color": [1, 0, 0], // Red
|
|
||||||
"BrickColor": "Bright red", // BrickColor name
|
"BrickColor": "Bright red", // BrickColor name
|
||||||
|
"Shape": "Ball", // Enum name
|
||||||
// UDim/UDim2 (nested objects)
|
"Tags": ["Collectible", "PowerUp"], // Array
|
||||||
"Size": {
|
"Size": { "X": {"Scale": 1, "Offset": 0}, "Y": {"Scale": 0, "Offset": 100} }, // UDim2
|
||||||
"X": {"Scale": 1, "Offset": 0},
|
"CFrame": { "position": [0, 5, 0], "orientation": [[1,0,0],[0,1,0],[0,0,1]] } // CFrame
|
||||||
"Y": {"Scale": 0, "Offset": 100}
|
|
||||||
},
|
|
||||||
|
|
||||||
// CFrame (special syntax)
|
|
||||||
"CFrame": [0, 5, 0], // Position only
|
|
||||||
"CFrame": {
|
|
||||||
"position": [0, 5, 0],
|
|
||||||
"orientation": [
|
|
||||||
[1, 0, 0],
|
|
||||||
[0, 1, 0],
|
|
||||||
[0, 0, 1]
|
|
||||||
]
|
|
||||||
},
|
|
||||||
|
|
||||||
// Enums (string names)
|
|
||||||
"Shape": "Ball",
|
|
||||||
"Material": "Plastic",
|
|
||||||
"FormFactor": "Symmetric",
|
|
||||||
|
|
||||||
// Arrays
|
|
||||||
"Tags": ["Collectible", "PowerUp"],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Explicit Type (When Needed)
|
### Explicit Type
|
||||||
|
|
||||||
|
Use when ambiguous or specifying enum by number:
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
"$properties": {
|
"$properties": {
|
||||||
// Explicit Vector3
|
"Position": { "Vector3": [0, 5, 0] },
|
||||||
"Position": {
|
"Shape": { "Enum": 1 },
|
||||||
"Vector3": [0, 5, 0]
|
"BrickColor": { "BrickColor": 21 }
|
||||||
},
|
|
||||||
|
|
||||||
// Explicit Color3
|
|
||||||
"Color": {
|
|
||||||
"Color3": [1, 0, 0]
|
|
||||||
},
|
|
||||||
|
|
||||||
// Explicit Enum (by number)
|
|
||||||
"Shape": {
|
|
||||||
"Enum": 1 // Ball = 1
|
|
||||||
},
|
|
||||||
|
|
||||||
// Explicit BrickColor (by number)
|
|
||||||
"BrickColor": {
|
|
||||||
"BrickColor": 21 // Bright red = 21
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**When to use explicit:**
|
|
||||||
- Ambiguous types
|
|
||||||
- Enum by number instead of name
|
|
||||||
- Overriding inferred type
|
|
||||||
|
|
||||||
## Attributes
|
## Attributes
|
||||||
|
|
||||||
|
Same format as properties. Limitations: no Ref, no NumberSequence/ColorSequence, enums use string names only.
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
"$attributes": {
|
"$attributes": {
|
||||||
// Primitives
|
|
||||||
"Health": 100,
|
"Health": 100,
|
||||||
"Speed": 16.5,
|
"Position": [0, 5, 0],
|
||||||
"IsEnemy": true,
|
"MyFont": { "family": "rbxasset://fonts/families/SourceSansPro.json", "weight": "Regular", "style": "Normal" }
|
||||||
"Description": "A powerful weapon",
|
|
||||||
|
|
||||||
// Supported types
|
|
||||||
"Position": [0, 5, 0], // Vector3
|
|
||||||
"Color": [1, 0, 0], // Color3
|
|
||||||
"MyFont": { // Font
|
|
||||||
"family": "rbxasset://fonts/families/SourceSansPro.json",
|
|
||||||
"weight": "Regular",
|
|
||||||
"style": "Normal"
|
|
||||||
},
|
|
||||||
"MyCFrame": { // CFrame
|
|
||||||
"position": [0, 0, 0],
|
|
||||||
"orientation": [[1,0,0],[0,1,0],[0,0,1]]
|
|
||||||
},
|
|
||||||
|
|
||||||
// Enums (string names only)
|
|
||||||
"Material": "Plastic"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Attribute limitations:**
|
|
||||||
- No Ref properties
|
|
||||||
- No complex types (NumberSequence, ColorSequence, etc.)
|
|
||||||
- Enums must use string names (not numbers)
|
|
||||||
|
|
||||||
## Ref Property Linking
|
## Ref Property Linking
|
||||||
|
|
||||||
**Problem:** Instances can reference other instances (e.g., `ObjectValue.Value`).
|
Link instances via `$id` and special attributes:
|
||||||
|
|
||||||
**Solution:** Use `$id` and special attributes:
|
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
"tree": {
|
"tree": {
|
||||||
"Target": {
|
"Target": { "$className": "Part", "$id": "myTarget" },
|
||||||
"$className": "Part",
|
|
||||||
"$id": "myTarget"
|
|
||||||
},
|
|
||||||
|
|
||||||
"Pointer": {
|
"Pointer": {
|
||||||
"$className": "ObjectValue",
|
"$className": "ObjectValue",
|
||||||
"$id": "myPointer",
|
"$attributes": { "Rojo_Target_Value": "myTarget" }
|
||||||
"$attributes": {
|
|
||||||
// Links Value property to instance with $id "myTarget"
|
|
||||||
"Rojo_Target_Value": "myTarget"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -461,310 +313,24 @@ ModuleScript "MyModule"
|
||||||
|
|
||||||
**Attribute format:** `Rojo_Target_<PropertyName>`
|
**Attribute format:** `Rojo_Target_<PropertyName>`
|
||||||
|
|
||||||
**Plugin handles linking:**
|
## Property Types
|
||||||
1. Reads `$id` from instances
|
|
||||||
2. Reads `Rojo_Target_*` attributes
|
|
||||||
3. Sets Ref properties to correct instances
|
|
||||||
|
|
||||||
## Sync Rules
|
`String`, `Bool`, `Int32`, `Int64`, `Float32`, `Float64`, `Vector2`, `Vector3`, `Vector2int16`, `Vector3int16`, `UDim`, `UDim2`, `CFrame`, `Color3`, `Color3uint8`, `BrickColor`, `NumberRange`, `Rect`, `NumberSequence`, `ColorSequence`, `Enum`, `Ref`, `Content`, `Font`, `PhysicalProperties`, `Axes`, `Faces`, `Tags`, `Attributes`
|
||||||
|
|
||||||
**Custom file type handling:**
|
See `rbx_reflection_database` for property listings per class.
|
||||||
|
|
||||||
```json5
|
## Validation Errors
|
||||||
{
|
|
||||||
"syncRules": [
|
|
||||||
{
|
|
||||||
// Required: Glob pattern (relative to project)
|
|
||||||
"pattern": "*.foo",
|
|
||||||
|
|
||||||
// Required: How to treat files
|
1. Unknown fields (except children)
|
||||||
"use": "text",
|
2. Reserved names starting with `$` as children
|
||||||
|
3. Missing `$className` or `$path`
|
||||||
|
4. `$path` to non-existent file
|
||||||
|
5. Invalid property types
|
||||||
|
6. Invalid glob syntax
|
||||||
|
7. Duplicate `$id`
|
||||||
|
|
||||||
// Optional: What to strip from filename
|
## Source Files
|
||||||
"suffix": ".foo",
|
|
||||||
|
|
||||||
// Optional: Exclude pattern
|
- `src/project.rs` - Project parsing
|
||||||
"exclude": "*.test.foo"
|
- `src/snapshot_middleware/mod.rs` - Extension mappings
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Available `use` Types
|
|
||||||
|
|
||||||
| `use` Value | Result | Notes |
|
|
||||||
|-------------|--------|-------|
|
|
||||||
| `serverScript` | Script (RunContext.Server) | Server-side script |
|
|
||||||
| `clientScript` | Script (RunContext.Client) | Client-side script |
|
|
||||||
| `moduleScript` | ModuleScript | Shared module |
|
|
||||||
| `pluginScript` | Script (RunContext.Plugin) | Plugin script |
|
|
||||||
| `localScript` | LocalScript | Legacy client script |
|
|
||||||
| `legacyScript` | Script (RunContext.Legacy) | Legacy server script |
|
|
||||||
| `json` | ModuleScript | JSON → Lua table |
|
|
||||||
| `toml` | ModuleScript | TOML → Lua table |
|
|
||||||
| `yaml` | ModuleScript | YAML → Lua table |
|
|
||||||
| `csv` | LocalizationTable | CSV localization |
|
|
||||||
| `text` | StringValue | Plain text |
|
|
||||||
| `jsonModel` | Instance tree | JSON model format |
|
|
||||||
| `rbxm` | Instance tree | Binary model |
|
|
||||||
| `rbxmx` | Instance tree | XML model |
|
|
||||||
| `project` | Nested project | Project file |
|
|
||||||
| `ignore` | (nothing) | Skip file entirely |
|
|
||||||
|
|
||||||
**Note:** These are the only valid `use` values. The Middleware enum uses camelCase serialization.
|
|
||||||
|
|
||||||
### Example: Custom Extension
|
|
||||||
|
|
||||||
```json5
|
|
||||||
{
|
|
||||||
"syncRules": [
|
|
||||||
{
|
|
||||||
"pattern": "*.component.tsx",
|
|
||||||
"use": "moduleScript",
|
|
||||||
"suffix": ".component.tsx"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Result:** `Button.component.tsx` → ModuleScript named "Button"
|
|
||||||
|
|
||||||
## Syncback Rules
|
|
||||||
|
|
||||||
```json5
|
|
||||||
{
|
|
||||||
"syncbackRules": {
|
|
||||||
// Ignore Roblox tree paths
|
|
||||||
"ignoreTrees": [
|
|
||||||
"ServerStorage/AdminTools",
|
|
||||||
"Workspace/Camera"
|
|
||||||
],
|
|
||||||
|
|
||||||
// Ignore filesystem paths (globs)
|
|
||||||
"ignorePaths": [
|
|
||||||
"src/generated/*",
|
|
||||||
"src/temp/**"
|
|
||||||
],
|
|
||||||
|
|
||||||
// Ignore properties by class
|
|
||||||
"ignoreProperties": {
|
|
||||||
"BasePart": ["Color", "BrickColor"],
|
|
||||||
"Script": ["Disabled"],
|
|
||||||
"LocalScript": ["Disabled"]
|
|
||||||
},
|
|
||||||
|
|
||||||
// Ignore entire classes during syncback
|
|
||||||
"ignoreClasses": [
|
|
||||||
"Terrain",
|
|
||||||
"Camera"
|
|
||||||
],
|
|
||||||
|
|
||||||
// Sync Workspace.CurrentCamera? (default: false)
|
|
||||||
"syncCurrentCamera": false,
|
|
||||||
|
|
||||||
// Sync unscriptable properties? (default: true)
|
|
||||||
"syncUnscriptable": true,
|
|
||||||
|
|
||||||
// Skip Ref properties like Model.PrimaryPart? (default: false)
|
|
||||||
"ignoreReferents": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Meta File Format
|
|
||||||
|
|
||||||
**Purpose:** Add metadata to instances created from files.
|
|
||||||
|
|
||||||
**Example:** `MyScript.server.lua` + `MyScript.server.meta.json5`
|
|
||||||
|
|
||||||
```json5
|
|
||||||
// MyScript.server.meta.json5
|
|
||||||
{
|
|
||||||
// Override className (rare)
|
|
||||||
"$className": "Script",
|
|
||||||
|
|
||||||
// Add properties
|
|
||||||
"$properties": {
|
|
||||||
"Disabled": false,
|
|
||||||
"RunContext": "Server"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Add attributes
|
|
||||||
"$attributes": {
|
|
||||||
"Priority": 1,
|
|
||||||
"LoadOrder": "First"
|
|
||||||
},
|
|
||||||
|
|
||||||
// Ignore unknown children during sync
|
|
||||||
"$ignoreUnknownInstances": true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Meta files CAN'T:**
|
|
||||||
- Override instance name (name comes from filename)
|
|
||||||
- Set `$path` (path is the .lua file)
|
|
||||||
- Have children (children come from directory)
|
|
||||||
|
|
||||||
**Meta files CAN:**
|
|
||||||
- Override `$className` (if middleware allows)
|
|
||||||
- Add `$properties`
|
|
||||||
- Add `$attributes`
|
|
||||||
- Set `$ignoreUnknownInstances`
|
|
||||||
|
|
||||||
## Model.json Format
|
|
||||||
|
|
||||||
**Inline instance definition:**
|
|
||||||
|
|
||||||
```json5
|
|
||||||
// Weapon.model.json5
|
|
||||||
{
|
|
||||||
// Required: Class name
|
|
||||||
"$className": "Tool",
|
|
||||||
|
|
||||||
// Optional: Properties
|
|
||||||
"$properties": {
|
|
||||||
"CanBeDropped": false,
|
|
||||||
"RequiresHandle": true
|
|
||||||
},
|
|
||||||
|
|
||||||
// Optional: Attributes
|
|
||||||
"$attributes": {
|
|
||||||
"Damage": 50,
|
|
||||||
"FireRate": 0.5
|
|
||||||
},
|
|
||||||
|
|
||||||
// Optional: Children
|
|
||||||
"Handle": {
|
|
||||||
"$className": "Part",
|
|
||||||
"$properties": {
|
|
||||||
"Size": [1, 1, 3],
|
|
||||||
"Anchored": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"Script": {
|
|
||||||
"$className": "Script",
|
|
||||||
"$properties": {
|
|
||||||
"Source": "print('tool equipped')"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Use case:** Small instances that don't need separate files.
|
|
||||||
|
|
||||||
## Common Patterns
|
|
||||||
|
|
||||||
### Multi-Place Game
|
|
||||||
|
|
||||||
```json5
|
|
||||||
{
|
|
||||||
"name": "MyGame",
|
|
||||||
"servePlaceIds": [123456, 789012], // Both places allowed
|
|
||||||
"tree": {
|
|
||||||
"ReplicatedStorage": {
|
|
||||||
"$path": "src/shared" // Shared code
|
|
||||||
},
|
|
||||||
"ServerScriptService": {
|
|
||||||
"$path": "src/server" // Server code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Library/Module
|
|
||||||
|
|
||||||
```json5
|
|
||||||
{
|
|
||||||
"name": "MyLibrary",
|
|
||||||
"tree": {
|
|
||||||
"$className": "ModuleScript",
|
|
||||||
"$path": "src/init.lua"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Result:** Single ModuleScript named "MyLibrary"
|
|
||||||
|
|
||||||
### Plugin
|
|
||||||
|
|
||||||
```json5
|
|
||||||
{
|
|
||||||
"name": "MyPlugin",
|
|
||||||
"tree": {
|
|
||||||
"$className": "Script",
|
|
||||||
"$path": "src/plugin.server.lua",
|
|
||||||
"$properties": {
|
|
||||||
"RunContext": "Plugin"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Validation Rules
|
|
||||||
|
|
||||||
**Rojo validates projects and provides errors:**
|
|
||||||
|
|
||||||
1. **Unknown fields** - Keys not recognized (except children)
|
|
||||||
2. **Reserved names starting with `$`** - Can't use as child names
|
|
||||||
3. **`$className` without `$path`** - Must set one or both
|
|
||||||
4. **`$path` pointing to non-existent file** - File must exist
|
|
||||||
5. **Invalid property types** - Type doesn't match property
|
|
||||||
6. **Glob pattern syntax** - Must be valid glob
|
|
||||||
7. **Duplicate `$id`** - IDs must be unique
|
|
||||||
|
|
||||||
## Property Type Reference
|
|
||||||
|
|
||||||
**Complete list of supported property types:**
|
|
||||||
|
|
||||||
- `String` - Text
|
|
||||||
- `Bool` - true/false
|
|
||||||
- `Int32`, `Int64` - Integers
|
|
||||||
- `Float32`, `Float64` - Decimals
|
|
||||||
- `Vector2`, `Vector3` - Vectors
|
|
||||||
- `Vector2int16`, `Vector3int16` - Integer vectors
|
|
||||||
- `UDim`, `UDim2` - UI dimensions
|
|
||||||
- `CFrame` - Coordinate frame
|
|
||||||
- `Color3`, `Color3uint8` - Colors
|
|
||||||
- `BrickColor` - Legacy colors
|
|
||||||
- `NumberRange` - Min/max range
|
|
||||||
- `Rect` - Rectangle
|
|
||||||
- `NumberSequence` - Animated number
|
|
||||||
- `ColorSequence` - Animated color
|
|
||||||
- `Enum` - Enumeration
|
|
||||||
- `Ref` - Instance reference
|
|
||||||
- `Content` - Asset URL
|
|
||||||
- `Font` - Font description
|
|
||||||
- `PhysicalProperties` - Part physics
|
|
||||||
- `Axes`, `Faces` - Part faces/axes
|
|
||||||
- `Tags` - CollectionService tags
|
|
||||||
- `Attributes` - Instance attributes
|
|
||||||
|
|
||||||
**See rbx_reflection_database for complete property listings per class.**
|
|
||||||
|
|
||||||
## Debugging Project Files
|
|
||||||
|
|
||||||
**Validate with:**
|
|
||||||
```bash
|
|
||||||
rojo build project.json5 -o test.rbxmx
|
|
||||||
```
|
|
||||||
|
|
||||||
**Check for:**
|
|
||||||
- Syntax errors (JSON5 parser)
|
|
||||||
- Unknown fields (validation)
|
|
||||||
- Missing files (path resolution)
|
|
||||||
- Type mismatches (property validation)
|
|
||||||
|
|
||||||
**Format project file:**
|
|
||||||
```bash
|
|
||||||
rojo fmt-project project.json5
|
|
||||||
```
|
|
||||||
|
|
||||||
Formats JSON, normalizes structure, sorts keys.
|
|
||||||
|
|
||||||
## Key Files to Reference
|
|
||||||
|
|
||||||
- `src/project.rs` - Project parsing and validation
|
|
||||||
- `src/snapshot_middleware/mod.rs` - File extension mappings
|
|
||||||
- `src/snapshot/` - Instance tree structure
|
- `src/snapshot/` - Instance tree structure
|
||||||
- `examples/` - Example project files (if exists)
|
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ pub fn syncback_loop(
|
||||||
|
|
||||||
**Default behavior.** Preserves existing file structure:
|
**Default behavior.** Preserves existing file structure:
|
||||||
|
|
||||||
- If `src/MyScript.lua` exists, update it
|
- If `src/MyScript.luau` exists, update it
|
||||||
- If `src/MyFolder/init.lua` exists (directory structure), preserve it
|
- If `src/MyFolder/init.luau` exists (directory structure), preserve it
|
||||||
- Only creates new files when instances don't match anything
|
- Only creates new files when instances don't match anything
|
||||||
- Compares hashes to detect actual changes (avoids rewriting unchanged files)
|
- Compares hashes to detect actual changes (avoids rewriting unchanged files)
|
||||||
|
|
||||||
|
|
@ -119,7 +119,7 @@ pub struct SyncbackRules {
|
||||||
- Filters out `Name`, `Parent` (always)
|
- Filters out `Name`, `Parent` (always)
|
||||||
- Filters out properties in `ignore_properties`
|
- Filters out properties in `ignore_properties`
|
||||||
- Filters out unscriptable properties if `sync_unscriptable: false`
|
- Filters out unscriptable properties if `sync_unscriptable: false`
|
||||||
- Filters out middleware-specific properties (e.g., `Script.Source` when writing to `.lua` file)
|
- Filters out middleware-specific properties (e.g., `Script.Source` when writing to `.luau` file)
|
||||||
|
|
||||||
### Hidden Services
|
### Hidden Services
|
||||||
|
|
||||||
|
|
@ -198,11 +198,11 @@ pub struct SyncbackSnapshot<'sync> {
|
||||||
```rust
|
```rust
|
||||||
// Join child to current path
|
// Join child to current path
|
||||||
snapshot.with_joined_path(new_ref, old_ref)?
|
snapshot.with_joined_path(new_ref, old_ref)?
|
||||||
// Result: parent_path/ChildName.lua
|
// Result: parent_path/ChildName.luau
|
||||||
|
|
||||||
// Use base path
|
// Use base path
|
||||||
snapshot.with_base_path(&base, new_ref, old_ref)?
|
snapshot.with_base_path(&base, new_ref, old_ref)?
|
||||||
// Result: base/ChildName.lua
|
// Result: base/ChildName.luau
|
||||||
|
|
||||||
// Explicit path
|
// Explicit path
|
||||||
snapshot.with_new_path(path, new_ref, old_ref)
|
snapshot.with_new_path(path, new_ref, old_ref)
|
||||||
|
|
@ -213,7 +213,7 @@ snapshot.with_new_path(path, new_ref, old_ref)
|
||||||
- Uses instance name
|
- Uses instance name
|
||||||
- Adds appropriate extension based on middleware
|
- Adds appropriate extension based on middleware
|
||||||
- Encodes Windows-invalid chars if enabled
|
- Encodes Windows-invalid chars if enabled
|
||||||
- Example: `Script` named "My Script" → `My Script.server.lua`
|
- Example: `Script` named "My Script" → `My Script.server.luau`
|
||||||
|
|
||||||
### Property Filtering
|
### Property Filtering
|
||||||
|
|
||||||
|
|
@ -232,7 +232,7 @@ snapshot.get_path_filtered_properties(new_ref)
|
||||||
**Decision tree:**
|
**Decision tree:**
|
||||||
|
|
||||||
1. **Old instance exists?** → Use same middleware as before (preserve structure)
|
1. **Old instance exists?** → Use same middleware as before (preserve structure)
|
||||||
2. **Script type?** → Choose appropriate Lua middleware (`.server.lua`, `.client.lua`, etc.)
|
2. **Script type?** → Choose appropriate Lua middleware (`.server.luau`, `.client.luau`, etc.)
|
||||||
3. **Model/container?** → Choose directory or rbxm based on complexity
|
3. **Model/container?** → Choose directory or rbxm based on complexity
|
||||||
4. **Special types?** → CSV for LocalizationTable, TXT for StringValue
|
4. **Special types?** → CSV for LocalizationTable, TXT for StringValue
|
||||||
5. **Fallback** → Rbxm or JsonModel
|
5. **Fallback** → Rbxm or JsonModel
|
||||||
|
|
@ -334,14 +334,14 @@ Script "MyScript"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Syncback produces:**
|
**Syncback produces:**
|
||||||
```lua
|
```luau
|
||||||
-- src/MyScript.server.lua
|
-- src/MyScript.server.luau
|
||||||
print('hello')
|
print('hello')
|
||||||
```
|
```
|
||||||
|
|
||||||
**Meta file (if needed):**
|
**Meta file (if needed):**
|
||||||
```json5
|
```json5
|
||||||
// src/MyScript.server.meta.json5
|
// src/MyScript.server.meta.json5 (for MyScript.server.luau)
|
||||||
{
|
{
|
||||||
"$properties": {
|
"$properties": {
|
||||||
"Disabled": false
|
"Disabled": false
|
||||||
|
|
@ -352,7 +352,7 @@ print('hello')
|
||||||
### Syncing a Model
|
### Syncing a Model
|
||||||
|
|
||||||
**Simple model (few children):** → `.rbxm` or `.rbxmx` file
|
**Simple model (few children):** → `.rbxm` or `.rbxmx` file
|
||||||
**Complex model (many children):** → Directory with `init.meta.json5`
|
**Complex model (many children):** → Directory with `init.meta.json5` or `init.luau`
|
||||||
|
|
||||||
### Syncing Nested Folders
|
### Syncing Nested Folders
|
||||||
|
|
||||||
|
|
@ -365,9 +365,9 @@ Roblox:
|
||||||
|
|
||||||
Filesystem:
|
Filesystem:
|
||||||
src/Modules/
|
src/Modules/
|
||||||
Utils.lua
|
Utils.luau
|
||||||
Math/
|
Math/
|
||||||
Add.lua
|
Add.luau
|
||||||
```
|
```
|
||||||
|
|
||||||
## Error Handling
|
## Error Handling
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,11 @@ This avoids manual tree manipulation bugs and handles complex cases (large model
|
||||||
|
|
||||||
## Project Files
|
## Project Files
|
||||||
|
|
||||||
`.project.json` or `.project.json5` (JSON5 preferred for comments):
|
`.project.json5` (preferred) | `.project.json` (legacy):
|
||||||
|
|
||||||
```json5
|
```json5
|
||||||
{
|
{
|
||||||
name: "MyProject", // Optional if default.project.json (inherits folder name)
|
name: "MyProject", // Optional if default.project.json5 (inherits folder name)
|
||||||
tree: {
|
tree: {
|
||||||
$path: "src"
|
$path: "src"
|
||||||
},
|
},
|
||||||
|
|
@ -50,8 +50,9 @@ This avoids manual tree manipulation bugs and handles complex cases (large model
|
||||||
|
|
||||||
**Key conventions:**
|
**Key conventions:**
|
||||||
- Services don't need explicit `$className` (inferred)
|
- Services don't need explicit `$className` (inferred)
|
||||||
- `default.project.json` inherits parent folder name
|
- `default.project.json5` inherits parent folder name
|
||||||
- Projects can be nested (each has independent sync rules)
|
- Projects can be nested (each has independent sync rules)
|
||||||
|
- **Use `.luau` for scripts, `.json5` for config** (`.lua`/`.json` are legacy but supported)
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
@ -66,7 +67,7 @@ For plugin work: Luau LSP, Studio with "Reload plugins on file change"
|
||||||
### Initial Setup
|
### Initial Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone --recursive https://github.com/rojo-rbx/rojo
|
git clone --recursive https://github.com/UserGeneratedLLC/rojo
|
||||||
cd rojo
|
cd rojo
|
||||||
rokit install # Installs tools from rokit.toml
|
rokit install # Installs tools from rokit.toml
|
||||||
cargo test # Verify setup
|
cargo test # Verify setup
|
||||||
|
|
@ -127,7 +128,7 @@ Every PR updates `CHANGELOG.md`:
|
||||||
|
|
||||||
* Made a change to Rojo ([#1234])
|
* Made a change to Rojo ([#1234])
|
||||||
|
|
||||||
[#1234]: https://github.com/rojo-rbx/rojo/pull/1234
|
[#1234]: https://github.com/UserGeneratedLLC/rojo/pull/1234
|
||||||
```
|
```
|
||||||
|
|
||||||
Keep link definitions in ascending order.
|
Keep link definitions in ascending order.
|
||||||
|
|
|
||||||
|
|
@ -38,25 +38,29 @@ pub struct InstanceSnapshot {
|
||||||
|
|
||||||
Transforms files → `InstanceSnapshot`. Main entry: `snapshot_from_vfs()`
|
Transforms files → `InstanceSnapshot`. Main entry: `snapshot_from_vfs()`
|
||||||
|
|
||||||
| File | Handler | Result |
|
| File | Handler | Result | Note |
|
||||||
|------|---------|--------|
|
|------|---------|--------|------|
|
||||||
| `*.lua` / `*.luau` | `lua.rs` | ModuleScript |
|
| `*.luau` | `lua.rs` | ModuleScript | Preferred |
|
||||||
| `*.server.luau` | `lua.rs` | Script (RunContext.Server) |
|
| `*.server.luau` | `lua.rs` | Script (RunContext.Server) | Preferred |
|
||||||
| `*.server.lua` | `lua.rs` | Script (RunContext.Legacy) |
|
| `*.client.luau` | `lua.rs` | Script (RunContext.Client) | Preferred |
|
||||||
| `*.client.luau` | `lua.rs` | Script (RunContext.Client) |
|
| `*.plugin.luau` | `lua.rs` | Script (RunContext.Plugin) | |
|
||||||
| `*.client.lua` | `lua.rs` | LocalScript |
|
| `*.local.luau` | `lua.rs` | LocalScript | |
|
||||||
| `*.plugin.lua(u)` | `lua.rs` | Script (RunContext.Plugin) |
|
| `*.legacy.luau` | `lua.rs` | Script (RunContext.Legacy) | |
|
||||||
| `*.local.lua(u)` | `lua.rs` | LocalScript |
|
| `*.lua` | `lua.rs` | ModuleScript | Legacy |
|
||||||
| `*.legacy.lua(u)` | `lua.rs` | Script (RunContext.Legacy) |
|
| `*.server.lua` | `lua.rs` | Script (RunContext.Legacy) | Legacy |
|
||||||
| `*.rbxm` / `*.rbxmx` | `rbxm.rs` / `rbxmx.rs` | Binary/XML model tree |
|
| `*.client.lua` | `lua.rs` | LocalScript | Legacy |
|
||||||
| `*.model.json` | `json_model.rs` | JSON instance |
|
| `*.rbxm` / `*.rbxmx` | `rbxm.rs` / `rbxmx.rs` | Binary/XML model tree | |
|
||||||
| `*.project.json` | `project.rs` | Nested project |
|
| `*.model.json5` | `json_model.rs` | JSON instance | Preferred |
|
||||||
| `*.csv` / `*.txt` | `csv.rs` / `txt.rs` | LocalizationTable / StringValue |
|
| `*.model.json` | `json_model.rs` | JSON instance | Legacy |
|
||||||
| `*.toml` / `*.json` / `*.yaml` | Data → ModuleScript |
|
| `*.project.json5` | `project.rs` | Nested project | Preferred |
|
||||||
| Directory | `dir.rs` | Folder or inferred service |
|
| `*.project.json` | `project.rs` | Nested project | Legacy |
|
||||||
| `*.meta.json` | `meta_file.rs` | Metadata overlay |
|
| `*.csv` / `*.txt` | `csv.rs` / `txt.rs` | LocalizationTable / StringValue | |
|
||||||
|
| `*.toml` / `*.json5` / `*.yaml` | Data → ModuleScript | |
|
||||||
|
| Directory | `dir.rs` | Folder or inferred service | |
|
||||||
|
| `*.meta.json5` | `meta_file.rs` | Metadata overlay | Preferred |
|
||||||
|
| `*.meta.json` | `meta_file.rs` | Metadata overlay | Legacy |
|
||||||
|
|
||||||
**Init files:** `init.lua`, `init.server.lua`, etc. → Instance named after parent directory
|
**Init files:** `init.luau`, `init.server.luau`, etc. → Instance named after parent directory (`.lua` legacy supported)
|
||||||
|
|
||||||
**Context passed to middleware:**
|
**Context passed to middleware:**
|
||||||
|
|
||||||
|
|
@ -94,7 +98,7 @@ Reverse: Roblox file → filesystem
|
||||||
|
|
||||||
### 6. Project System (`src/project.rs`)
|
### 6. Project System (`src/project.rs`)
|
||||||
|
|
||||||
Parse/validate `.project.json`, handle nested projects, manage sync rules.
|
Parse/validate `.project.json5` (or legacy `.project.json`), handle nested projects, manage sync rules.
|
||||||
|
|
||||||
## Command Implementations
|
## Command Implementations
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue