roport 1.0.1 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +16 -0
  2. package/bin/roport.js +2 -1
  3. package/package.json +2 -2
  4. package/src/server.js +171 -10
  5. package/templates/default/DOCUMENTATION.md +309 -0
  6. package/templates/default/README.md +35 -0
  7. package/templates/default/RoportSyncPlugin.rbxmx +1315 -0
  8. package/templates/default/default.project.json +6 -0
  9. package/templates/default/src/Roport/Modules/Sync.lua +10 -6
  10. package/templates/default/src/Roport/init.server.lua +66 -0
  11. package/templates/default/src/lighting/Atmosphere/init.meta.json +1 -1
  12. package/templates/default/src/lighting/Bloom/init.meta.json +1 -1
  13. package/templates/default/src/lighting/DepthOfField/init.meta.json +1 -1
  14. package/templates/default/src/lighting/Sky/init.meta.json +1 -1
  15. package/templates/default/src/lighting/SunRays/init.meta.json +1 -1
  16. package/templates/default/src/server/network/CombatHandler.server.luau +2 -1
  17. package/templates/default/src/server/network/ShopHandler.server.luau +6 -5
  18. package/templates/default/src/server/world/WorldLoader.server.luau +7 -9
  19. package/templates/default/src/shared/Prefabs/ExampleTree/Part/init.meta.json +10 -0
  20. package/templates/default/src/shared/Prefabs/ExampleTree/init.meta.json +6 -0
  21. package/templates/default/src/shared/Prefabs/init.meta.json +6 -0
  22. package/templates/default/src/shared/movement/Pathfind.luau +42 -0
  23. package/templates/default/src/shared/network/Network.luau +1 -1
  24. package/templates/default/src/workspace/Accessory Storage/init.meta.json +1 -1
  25. package/templates/default/src/workspace/Baseplate/Texture/init.meta.json +1 -1
  26. package/templates/default/src/workspace/Baseplate/init.meta.json +1 -1
  27. package/templates/default/src/workspace/Map/Decorated old roblox house/Model/FirstFloor/Model/Smooth Block Model/Snap/init.meta.json +1 -1
  28. package/templates/default/src/workspace/Map/Decorated old roblox house/Model/FirstFloor/Model/Smooth Block Model/Weld/init.meta.json +1 -1
  29. package/templates/default/src/workspace/Map/Decorated old roblox house/Model/FirstFloor/Model/Smooth Block Model/init.meta.json +1 -1
  30. package/templates/default/src/workspace/Map/Decorated old roblox house/Model/FirstFloor/Model/init.meta.json +1 -1
  31. package/templates/default/src/workspace/Map/Decorated old roblox house/Model/FirstFloor/init.meta.json +1 -1
  32. package/templates/default/src/workspace/Map/Decorated old roblox house/Model/init.meta.json +1 -1
  33. package/templates/default/src/workspace/Map/Decorated old roblox house/init.meta.json +1 -1
  34. package/templates/default/src/workspace/Map/init.meta.json +1 -1
  35. package/templates/default/src/workspace/Part2/Decal/init.meta.json +1 -1
  36. package/templates/default/src/workspace/Part2/init.meta.json +1 -1
  37. package/templates/default/src/workspace/SpawnLocation/Decal/init.meta.json +1 -1
  38. package/templates/default/src/workspace/SpawnLocation/init.meta.json +1 -1
  39. package/templates/default/AI_INSTRUCTIONS.md +0 -72
package/README.md CHANGED
@@ -45,3 +45,19 @@ This will start a local server on port `3456` (default).
45
45
  3. Start the server with `roport serve`.
46
46
  4. Install the **Roport** plugin in Roblox Studio.
47
47
  5. Connect via the plugin in Roblox Studio.
48
+
49
+ ## Diagnostics
50
+
51
+ When the Roport plugin loads in Roblox Studio, it will automatically run a diagnostic check and output the results to the Output window. This check verifies:
52
+ - Connection to the Roport server.
53
+ - Correct mapping of project folders (`Shared`, `Server`, `Client`).
54
+
55
+ Look for the `[Roport]` prefix in the console to see the status.
56
+
57
+ ## Testing
58
+
59
+ To run the integration test suite for the CLI:
60
+
61
+ ```bash
62
+ node test/test_suite.js
63
+ ```
package/bin/roport.js CHANGED
@@ -33,7 +33,8 @@ program
33
33
  await fs.copy(templateDir, targetDir);
34
34
  console.log(chalk.green('Success! Project initialized.'));
35
35
  console.log(chalk.white('Run `roport serve` to start the sync server.'));
36
- console.log(chalk.white('Check AI_INSTRUCTIONS.md for usage details.'));
36
+ console.log(chalk.white('Check DOCUMENTATION.md for usage details.'));
37
+ console.log(chalk.white('Install RoportSyncPlugin.rbxmx in your Roblox Studio project.'));
37
38
  } else {
38
39
  console.error(chalk.red(`Error: Template directory not found at ${templateDir}`));
39
40
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "roport",
3
- "version": "1.0.1",
4
- "description": "A sync server for Roblox development. Works with the Roport Roblox Plugin.",
3
+ "version": "1.3.1",
4
+ "description": "A sync server for Roblox development. Works with the Roport Roblox Plugin. Features AI integration and full project sync.",
5
5
  "main": "src/server.js",
6
6
  "bin": {
7
7
  "roport": "./bin/roport.js"
package/src/server.js CHANGED
@@ -19,6 +19,7 @@ function startServer(port) {
19
19
  // State for two-way sync
20
20
  let changedFiles = new Set();
21
21
  let commandQueue = []; // Queue for commands to be sent to Roblox
22
+ let executionResults = new Map(); // Store results of executed scripts
22
23
  let isWriting = false; // Lock to prevent loops (Roblox -> File -> Watcher -> Roblox)
23
24
 
24
25
  // Watch for file changes locally
@@ -26,11 +27,11 @@ function startServer(port) {
26
27
  console.log(chalk.gray(`Starting file watcher on ${projectRoot}...`));
27
28
  fs.watch(projectRoot, { recursive: true }, (eventType, filename) => {
28
29
  if (filename && !isWriting) {
29
- // Ignore system folders and the cli folder itself if we are watching root
30
- if (filename.includes('node_modules') || filename.includes('.git') || filename.startsWith('cli')) return;
31
-
32
30
  // Normalize path to forward slashes
33
31
  const relativePath = filename.replace(/\\/g, '/');
32
+
33
+ // Check ignore rules
34
+ if (isIgnored(relativePath)) return;
34
35
 
35
36
  // Debounce/Deduplicate slightly
36
37
  if (!changedFiles.has(relativePath)) {
@@ -46,6 +47,125 @@ function startServer(port) {
46
47
  // Increase limit for large file batches
47
48
  app.use(express.json({ limit: '50mb' }));
48
49
 
50
+ // Ignore Logic
51
+ let ignoreRules = [];
52
+
53
+ function loadIgnoreRules() {
54
+ ignoreRules = [];
55
+ const ignoreFiles = ['.rojoignore', '.gitignore'];
56
+
57
+ for (const file of ignoreFiles) {
58
+ const ignorePath = path.join(projectRoot, file);
59
+ if (fs.existsSync(ignorePath)) {
60
+ try {
61
+ const content = fs.readFileSync(ignorePath, 'utf8');
62
+ const lines = content.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#'));
63
+ ignoreRules.push(...lines);
64
+ console.log(chalk.gray(`Loaded ${lines.length} ignore rules from ${file}`));
65
+ } catch (e) {
66
+ console.warn(chalk.yellow(`Failed to read ${file}:`), e);
67
+ }
68
+ }
69
+ }
70
+ // Always ignore internal folders
71
+ ignoreRules.push('.git', 'node_modules', 'cli');
72
+ }
73
+ loadIgnoreRules();
74
+
75
+ function isIgnored(filePath) {
76
+ // Normalize path
77
+ const relativePath = filePath.replace(/\\/g, '/');
78
+
79
+ for (const rule of ignoreRules) {
80
+ // Simple glob matching
81
+ // 1. Exact match
82
+ if (relativePath === rule) return true;
83
+
84
+ // 2. Directory match (rule ends with /)
85
+ if (rule.endsWith('/') && relativePath.startsWith(rule)) return true;
86
+
87
+ // 3. Extension match (*.lua)
88
+ if (rule.startsWith('*.') && relativePath.endsWith(rule.slice(1))) return true;
89
+
90
+ // 4. Folder match (node_modules) - check if it's a segment
91
+ if (!rule.includes('/') && !rule.includes('*')) {
92
+ const segments = relativePath.split('/');
93
+ if (segments.includes(rule)) return true;
94
+ }
95
+
96
+ // 5. Basic wildcard (src/*)
97
+ if (rule.endsWith('/*')) {
98
+ const base = rule.slice(0, -2);
99
+ if (relativePath.startsWith(base + '/') && relativePath.split('/').length === base.split('/').length + 1) return true;
100
+ }
101
+
102
+ // 6. Recursive wildcard (src/**)
103
+ if (rule.endsWith('/**')) {
104
+ const base = rule.slice(0, -3);
105
+ if (relativePath.startsWith(base + '/')) return true;
106
+ }
107
+ }
108
+ return false;
109
+ }
110
+
111
+ // Project Configuration Parsing
112
+ function getProjectConfig() {
113
+ const configPath = path.join(projectRoot, 'default.project.json');
114
+ if (fs.existsSync(configPath)) {
115
+ try {
116
+ const config = fs.readJsonSync(configPath);
117
+ const mounts = [];
118
+
119
+ function traverse(node, currentPath) {
120
+ if (node.$path) {
121
+ mounts.push({
122
+ robloxPath: currentPath,
123
+ filePath: node.$path,
124
+ className: node.$className
125
+ });
126
+ }
127
+
128
+ for (const key in node) {
129
+ if (!key.startsWith('$') && typeof node[key] === 'object') {
130
+ traverse(node[key], [...currentPath, key]);
131
+ }
132
+ }
133
+ }
134
+
135
+ if (config.tree) {
136
+ traverse(config.tree, []);
137
+ }
138
+
139
+ return { name: config.name, mounts };
140
+ } catch (e) {
141
+ console.error(chalk.red("Failed to parse default.project.json:"), e);
142
+ }
143
+ }
144
+ return null;
145
+ }
146
+
147
+ app.get('/config', (req, res) => {
148
+ const config = getProjectConfig();
149
+ if (config) {
150
+ res.send(config);
151
+ } else {
152
+ // Fallback for legacy projects without config
153
+ res.send({
154
+ mounts: [
155
+ { robloxPath: ["ServerScriptService"], filePath: "src/server" },
156
+ { robloxPath: ["ReplicatedStorage"], filePath: "src/shared" },
157
+ { robloxPath: ["StarterPlayer", "StarterPlayerScripts"], filePath: "src/client" },
158
+ { robloxPath: ["Workspace"], filePath: "src/workspace" },
159
+ { robloxPath: ["StarterGui"], filePath: "src/interface" },
160
+ { robloxPath: ["StarterPack"], filePath: "src/tools" },
161
+ { robloxPath: ["Lighting"], filePath: "src/lighting" },
162
+ { robloxPath: ["ReplicatedFirst"], filePath: "src/first" },
163
+ { robloxPath: ["SoundService"], filePath: "src/sounds" }
164
+ ]
165
+ });
166
+ }
167
+ });
168
+
49
169
  app.get('/ping', (req, res) => {
50
170
  res.send('pong');
51
171
  });
@@ -100,17 +220,48 @@ function startServer(port) {
100
220
  });
101
221
 
102
222
  app.post('/log', (req, res) => {
103
- const { message, stack, timestamp } = req.body;
104
- const timeStr = new Date(timestamp * 1000).toLocaleTimeString();
223
+ const { message, type, timestamp } = req.body;
224
+ const timeStr = new Date((timestamp || Date.now() / 1000) * 1000).toLocaleTimeString();
105
225
 
106
- console.log(chalk.red(`[ROBLOX ERROR ${timeStr}]`));
107
- console.log(chalk.red(message));
108
- if (stack) {
109
- console.log(chalk.gray(stack));
110
- }
226
+ let color = chalk.white;
227
+ if (type === 2 || type === 'Error') color = chalk.red; // Error
228
+ else if (type === 1 || type === 'Warning') color = chalk.yellow; // Warning
229
+
230
+ console.log(chalk.gray(`[STUDIO ${timeStr}]`) + " " + color(message));
231
+ res.send({ success: true });
232
+ });
233
+
234
+ // AI Interface: Remote Execution
235
+ app.post('/execute', (req, res) => {
236
+ const { code } = req.body;
237
+ if (!code) return res.status(400).send('Missing code');
238
+
239
+ const id = Date.now().toString();
240
+ commandQueue.push({ type: 'EXECUTE', id, code });
241
+ console.log(chalk.blue(`Queued execution ${id}`));
242
+
243
+ // Wait for result (long polling implementation could be better, but simple polling works for now)
244
+ res.send({ id, status: 'queued' });
245
+ });
246
+
247
+ app.post('/execute-result', (req, res) => {
248
+ const { id, success, result, error } = req.body;
249
+ executionResults.set(id, { success, result, error });
250
+ console.log(chalk.blue(`Received result for ${id}: ${success ? 'Success' : 'Failed'}`));
111
251
  res.send({ success: true });
112
252
  });
113
253
 
254
+ app.get('/execute/:id', (req, res) => {
255
+ const { id } = req.params;
256
+ if (executionResults.has(id)) {
257
+ const result = executionResults.get(id);
258
+ executionResults.delete(id); // Consume result
259
+ res.send({ status: 'completed', ...result });
260
+ } else {
261
+ res.send({ status: 'pending' });
262
+ }
263
+ });
264
+
114
265
  app.post('/command', (req, res) => {
115
266
  const { type, path } = req.body;
116
267
  if (!type) return res.status(400).send('Missing command type');
@@ -141,6 +292,11 @@ function startServer(port) {
141
292
  continue;
142
293
  }
143
294
 
295
+ if (isIgnored(filePath)) {
296
+ console.log(chalk.gray(`Skipping ignored file: ${filePath}`));
297
+ continue;
298
+ }
299
+
144
300
  if (filePath.endsWith('.json')) {
145
301
  try {
146
302
  const json = JSON.parse(content);
@@ -181,6 +337,11 @@ function startServer(port) {
181
337
  continue;
182
338
  }
183
339
 
340
+ if (isIgnored(filePath)) {
341
+ console.log(chalk.gray(`Skipping ignored file deletion: ${filePath}`));
342
+ continue;
343
+ }
344
+
184
345
  if (await fs.pathExists(safePath)) {
185
346
  await fs.remove(safePath);
186
347
  console.log(chalk.magenta(`Deleted: ${filePath}`));
@@ -0,0 +1,309 @@
1
+ # Roport Documentation
2
+
3
+ Roport is a two-way synchronization tool for Roblox development, designed to bridge the gap between Visual Studio Code and Roblox Studio. It allows developers to write code in external editors and have it instantly reflected in Roblox Studio, and vice versa.
4
+
5
+ This documentation provides a comprehensive reference for the CLI, Server API, Plugin features, and configuration formats.
6
+
7
+ ---
8
+
9
+ ## 1. Command Line Interface (CLI)
10
+
11
+ The `roport` CLI is the entry point for managing projects and running the sync server.
12
+
13
+ ### `roport init`
14
+ Initializes a new Roport project in the current directory.
15
+
16
+ **Description:**
17
+ Scaffolds a standard project structure including:
18
+ - `default.project.json`: The project configuration file.
19
+ - `src/`: A standard directory structure for Roblox services (server, client, shared, etc.).
20
+ - `RoportSyncPlugin.rbxmx`: The Roblox Studio plugin file.
21
+ - `README.md`: Basic usage instructions.
22
+
23
+ **Usage:**
24
+ ```bash
25
+ roport init
26
+ ```
27
+
28
+ ### `roport serve`
29
+ Starts the synchronization server.
30
+
31
+ **Description:**
32
+ Launches an HTTP server that listens for connections from the Roblox Studio plugin. It also starts a file watcher to detect changes in the local file system.
33
+
34
+ **Options:**
35
+ - `-p, --port <number>`: Specifies the port to run the server on. Default is `3456`.
36
+
37
+ **Usage:**
38
+ ```bash
39
+ roport serve
40
+ roport serve --port 8080
41
+ ```
42
+
43
+ ---
44
+
45
+ ## 2. Server API Reference
46
+
47
+ The Roport server exposes a RESTful API used by the Roblox Studio plugin. All endpoints accept and return JSON.
48
+
49
+ ### `GET /config`
50
+ Retrieves the project configuration.
51
+
52
+ **Description:**
53
+ Parses the `default.project.json` file and returns a flattened list of "mounts". A mount maps a Roblox service path (e.g., `ServerScriptService`) to a local file system path (e.g., `src/server`).
54
+
55
+ **Response:**
56
+ ```json
57
+ {
58
+ "name": "ProjectName",
59
+ "mounts": [
60
+ {
61
+ "robloxPath": ["ServerScriptService"],
62
+ "filePath": "src/server",
63
+ "className": "Folder"
64
+ }
65
+ ]
66
+ }
67
+ ```
68
+
69
+ ### `GET /poll`
70
+ Checks for updates from the file system.
71
+
72
+ **Description:**
73
+ Called periodically by the plugin (Long Polling). Returns a list of files that have changed or been deleted locally since the last poll, and any queued commands.
74
+
75
+ **Response:**
76
+ ```json
77
+ {
78
+ "changes": [
79
+ { "filePath": "src/server/script.server.luau", "content": "print('Hello')" },
80
+ { "filePath": "src/server/folder", "isDirectory": true }
81
+ ],
82
+ "deletions": [
83
+ "src/server/old_script.server.luau"
84
+ ],
85
+ "commands": []
86
+ }
87
+ ```
88
+
89
+ ### `POST /batch`
90
+ Uploads a batch of files from Roblox Studio to the file system.
91
+
92
+ **Description:**
93
+ Used during "Sync All" or "Auto-Sync" from Studio. Writes multiple files to disk.
94
+
95
+ **Request Body:**
96
+ ```json
97
+ {
98
+ "files": [
99
+ { "filePath": "src/server/script.server.luau", "content": "..." }
100
+ ]
101
+ }
102
+ ```
103
+
104
+ ### `POST /delete`
105
+ Deletes files from the file system.
106
+
107
+ **Description:**
108
+ Triggered when an instance is deleted or renamed in Roblox Studio.
109
+
110
+ **Request Body:**
111
+ ```json
112
+ {
113
+ "files": [
114
+ "src/server/deleted_script.server.luau"
115
+ ]
116
+ }
117
+ ```
118
+
119
+ ### `POST /command`
120
+ Queues a command to be executed by the plugin.
121
+
122
+ **Description:**
123
+ Allows external tools to trigger actions in Roblox Studio (e.g., starting a playtest).
124
+
125
+ **Request Body:**
126
+ ```json
127
+ {
128
+ "type": "PLAYTEST_START",
129
+ "path": null
130
+ }
131
+ ```
132
+
133
+ ### `POST /log`
134
+ Logs a message from Roblox Studio to the server console.
135
+
136
+ **Description:**
137
+ Useful for debugging plugin issues or forwarding Studio output to the terminal.
138
+
139
+ **Request Body:**
140
+ ```json
141
+ {
142
+ "message": "Error in script...",
143
+ "stack": "Stack trace...",
144
+ "timestamp": 1678888888
145
+ }
146
+ ```
147
+
148
+ ### `GET /ping`
149
+ Health check endpoint.
150
+
151
+ **Description:**
152
+ Returns `pong`. Used by the plugin to detect if the server is online.
153
+
154
+ ---
155
+
156
+ ## 3. AI Agent Integration
157
+
158
+ Roport includes features specifically designed to allow AI agents to control Roblox Studio autonomously.
159
+
160
+ ### Log Streaming
161
+ The plugin automatically hooks into `LogService.MessageOut` and streams all Studio output to the Roport server console.
162
+
163
+ - **Format:** `[STUDIO HH:MM:SS] Message`
164
+ - **Colors:**
165
+ - White: Standard Output (`print`)
166
+ - Yellow: Warnings (`warn`)
167
+ - Red: Errors (`error`)
168
+
169
+ **Usage for AI:**
170
+ An AI agent running the server can monitor `stdout` to see runtime errors, debugging information, or game state printed by scripts.
171
+
172
+ ### Remote Execution (REPL)
173
+ Allows an AI to execute arbitrary Luau code in the running Roblox Studio instance.
174
+
175
+ #### 1. Execute Code
176
+ **Endpoint:** `POST /execute`
177
+
178
+ **Request Body:**
179
+ ```json
180
+ {
181
+ "code": "return workspace.Part.Position"
182
+ }
183
+ ```
184
+
185
+ **Response:**
186
+ ```json
187
+ {
188
+ "id": "1678889999000",
189
+ "status": "queued"
190
+ }
191
+ ```
192
+
193
+ #### 2. Get Result
194
+ **Endpoint:** `GET /execute/:id`
195
+
196
+ **Response (Pending):**
197
+ ```json
198
+ { "status": "pending" }
199
+ ```
200
+
201
+ **Response (Completed):**
202
+ ```json
203
+ {
204
+ "status": "completed",
205
+ "success": true,
206
+ "result": "{\"X\":0,\"Y\":10,\"Z\":0}",
207
+ "error": null
208
+ }
209
+ ```
210
+
211
+ **Usage for AI:**
212
+ 1. **Inspect State:** Check properties of objects that aren't easily visible in files (e.g., physics state, player count).
213
+ 2. **Unit Testing:** Run test functions and check the output.
214
+ 3. **Manipulation:** Create temporary parts or modify the environment to test mechanics.
215
+
216
+ ---
217
+
218
+ ## 4. Plugin Features
219
+
220
+ The `RoportSyncPlugin` is a Roblox Studio plugin that connects to the Roport server.
221
+
222
+ ### Sync Panel
223
+ The main interface for the plugin.
224
+ - **Connect:** Establishes a connection to the server.
225
+ - **Sync All (Push):** Scans the entire Roblox workspace (based on configured mounts) and uploads all scripts and supported instances to the file system.
226
+ - **Pull Changes:** Manually fetches pending changes from the server.
227
+ - **Auto-Sync:** Toggles automatic uploading of changes made in Studio (scripts, properties, hierarchy) to the file system.
228
+ - **Auto-Pull:** Toggles automatic polling for changes made in the file system.
229
+
230
+ ### Settings
231
+ Configurable via the "Settings" button in the panel.
232
+ - **Server Port:** Must match the port used in `roport serve`. Default: `3456`.
233
+ - **Sync Interval:** How often (in seconds) Auto-Sync checks for dirty scripts. Default: `2`.
234
+
235
+ ### Synchronization Logic
236
+ - **Path Resolution:** The plugin uses the configuration from `/config` to determine where instances belong.
237
+ - **Two-Way Sync:**
238
+ - **Studio -> Disk:** Listens to `ScriptEditorService`, `AncestryChanged`, and `PropertyChangedSignal`.
239
+ - **Disk -> Studio:** Polls `/poll` for file changes and applies them using `Script.Source` or property updates.
240
+
241
+ ---
242
+
243
+ ## 4. Configuration
244
+
245
+ ### `default.project.json`
246
+ Defines the mapping between the file system and the Roblox DataModel.
247
+
248
+ **Structure:**
249
+ ```json
250
+ {
251
+ "name": "MyProject",
252
+ "tree": {
253
+ "$className": "DataModel",
254
+ "ServerScriptService": {
255
+ "$className": "ServerScriptService",
256
+ "$path": "src/server"
257
+ },
258
+ "ReplicatedStorage": {
259
+ "$className": "ReplicatedStorage",
260
+ "$path": "src/shared"
261
+ }
262
+ // ... other services
263
+ }
264
+ }
265
+ ```
266
+ - **$path:** The local directory path relative to the project root.
267
+ - **$className:** The Roblox ClassName for the container (usually a Service or Folder).
268
+
269
+ ### `.rojoignore` / `.gitignore`
270
+ Specifies files and directories to exclude from synchronization.
271
+
272
+ **Supported Patterns:**
273
+ - `*.txt`: Ignore all text files.
274
+ - `dist/`: Ignore the `dist` directory.
275
+ - `src/private/**`: Recursive ignore.
276
+ - `node_modules`: Exact folder match.
277
+
278
+ **Default Ignores:**
279
+ - `.git`
280
+ - `node_modules`
281
+ - `cli`
282
+
283
+ ---
284
+
285
+ ## 5. File Type Support
286
+
287
+ Roport maps file extensions to Roblox Instance types.
288
+
289
+ ### Scripts
290
+ - **`.server.luau` / `.server.lua`**: Creates a `Script` (RunContext=Legacy/Server).
291
+ - **`.client.luau` / `.client.lua`**: Creates a `LocalScript`.
292
+ - **`.luau` / `.lua`**: Creates a `ModuleScript`.
293
+ - **`init.server.luau`**: Creates a `Script` that is the parent of its directory's contents.
294
+
295
+ ### Data
296
+ - **`.json`**: Creates a `ModuleScript` returning the JSON table (unless it is a meta file).
297
+ - **`.txt`**: Creates a `StringValue`.
298
+
299
+ ### Models
300
+ - **`.rbxmx`**: Parses the Roblox XML Model format and reconstructs the Instance tree. Supports complex properties like `Vector3`, `Color3`, `UDim2`.
301
+
302
+ ### Metadata
303
+ - **`.meta.json`**: Defines properties for a folder or specific instance.
304
+ - Example: `Folder/init.meta.json` sets properties for `Folder`.
305
+ - **`.model.json`**: Similar to meta, used for defining class types and properties for generic files.
306
+
307
+ **Supported Properties in JSON/XML:**
308
+ - Primitives: `string`, `boolean`, `number`
309
+ - Complex: `Vector3`, `Color3`, `UDim2`, `UDim`, `Rect`, `NumberRange`
@@ -0,0 +1,35 @@
1
+ # Roport Project
2
+
3
+ This project was initialized with [Roport](https://github.com/Rydaguy101/RojoExportPlugin).
4
+
5
+ ## Getting Started
6
+
7
+ 1. **Install the Plugin:**
8
+ * Open Roblox Studio.
9
+ * Drag and drop `RoportSyncPlugin.rbxmx` into the 3D view.
10
+ * Right-click the created folder/script in the workspace and "Save as Local Plugin" (or just keep it in ServerStorage if you prefer).
11
+
12
+ 2. **Start the Server:**
13
+ * Run `roport serve` in this directory.
14
+ * The server will start on port 3456.
15
+
16
+ 3. **Connect:**
17
+ * In Roblox Studio, open the "Roport Sync" panel (Plugins tab).
18
+ * Click "Connect".
19
+ * Click "Sync All" to push the initial project structure to Roblox.
20
+
21
+ ## Project Structure
22
+
23
+ * `src/server`: Server-side scripts (`ServerScriptService`).
24
+ * `src/client`: Client-side scripts (`StarterPlayerScripts`).
25
+ * `src/shared`: Shared modules (`ReplicatedStorage`).
26
+ * `default.project.json`: Configuration for file paths.
27
+
28
+ ## Features
29
+
30
+ * **Two-Way Sync:** Edits in VS Code sync to Studio. Edits in Studio sync to VS Code (if Auto-Sync is on).
31
+ * **AI Integration:** Logs from Studio are streamed to the terminal. You can execute code remotely via the API.
32
+
33
+ ## Documentation
34
+
35
+ For full details on the CLI, API, and Configuration, see [DOCUMENTATION.md](./DOCUMENTATION.md).