@adiholick/nvstudio-mcp 2.0.1 → 2.0.3
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.
- package/README.md +43 -15
- package/dist/build-plugin.js +16 -10
- package/package.json +2 -2
- package/studio-plugin/Main.server.lua +9 -1
- package/studio-plugin/nvstudio_mcp.rbxmx +30 -25
- package/studio-plugin/ui_manager.lua +2 -2
package/README.md
CHANGED
|
@@ -8,9 +8,14 @@ Sistem ini didesain menggunakan **Hybrid Architecture** yang memisahkan logika E
|
|
|
8
8
|
|
|
9
9
|
## 📥 Instalasi
|
|
10
10
|
|
|
11
|
-
Langkah
|
|
11
|
+
Langkah instalasi dirancang **sangat mudah dan otomatis!**
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
> 💡 **Apakah perlu install plugin Roblox secara manual?**
|
|
14
|
+
> **TIDAK PERLU.** Jika Anda menjalankan skrip installer di bawah (Langkah 1), installer akan **secara otomatis menyalin plugin (`nvstudio_mcp.rbxmx`)** langsung ke folder plugin Roblox Studio di sistem operasi Anda.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
### Langkah 1: Jalankan Installer (Otomatis & Direkomendasikan)
|
|
14
19
|
|
|
15
20
|
Pilih perintah sesuai terminal yang Anda gunakan:
|
|
16
21
|
|
|
@@ -24,25 +29,40 @@ irm https://raw.githubusercontent.com/Adiholick/nvstudio-mcp/main/install.ps1 |
|
|
|
24
29
|
curl -fsSL https://raw.githubusercontent.com/Adiholick/nvstudio-mcp/main/install.sh | bash
|
|
25
30
|
```
|
|
26
31
|
|
|
32
|
+
**Apa saja yang dilakukan installer ini secara otomatis?**
|
|
33
|
+
1. 📦 Mengunduh source code, memasang dependensi Node.js, dan mengkompilasi TypeScript (*Bridge Server*).
|
|
34
|
+
2. 🧩 **Memasang Plugin Roblox Studio (`nvstudio_mcp.rbxmx`) otomatis** ke folder sistem Roblox Studio Anda (`%LOCALAPPDATA%\Roblox\Plugins` di Windows atau `~/Documents/ROBLOX/Plugins` di macOS).
|
|
35
|
+
3. 🤖 Mengintegrasikan *AI Agent Skills* anti-halusinasi langsung ke **Antigravity IDE** (`~/.gemini/config/plugins/nvstudio-mcp`).
|
|
36
|
+
4. ⚙️ Melakukan auto-konfigurasi jika mendeteksi editor **Cursor** (`.cursor/mcp.json`).
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
- Memasang dependensi Node.js dan melakukan kompilasi TypeScript (*Bridge Server*).
|
|
30
|
-
- Menyalin file plugin `nvstudio_mcp.rbxmx` ke dalam sistem Plugin Roblox Studio di OS Anda (Windows/macOS/WSL) secara otomatis.
|
|
31
|
-
- Mengintegrasikan *AI Agent Skills* langsung ke **Antigravity IDE** (`~/.gemini/config/plugins/nvstudio-mcp`).
|
|
32
|
-
- Melakukan auto-konfigurasi JSON jika Anda menggunakan **Cursor Editor**.
|
|
38
|
+
---
|
|
33
39
|
|
|
34
|
-
### 2
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
### Langkah 2: Mengaktifkan Izin di Roblox Studio (Wajib)
|
|
41
|
+
|
|
42
|
+
Karena pembatasan keamanan bawaan Roblox Studio, akses HTTP harus diizinkan sekali per place/game:
|
|
43
|
+
1. Buka game/place Anda di **Roblox Studio**.
|
|
44
|
+
2. Di toolbar atas, buka tab **Home** ➔ **Game Settings** ➔ pilih menu **Security**.
|
|
45
|
+
3. Centang (aktifkan) **`Allow HTTP Requests`**, lalu klik **Save**.
|
|
46
|
+
4. **Auto-Detect Aktif!** Plugin Roblox Studio kini memiliki heartbeat pintar yang akan otomatis terhubung (*Auto-Connect*) segera setelah MCP server aktif — Anda tidak perlu lagi repot menekan tombol connect secara manual.
|
|
38
47
|
|
|
39
48
|
---
|
|
40
49
|
|
|
41
|
-
|
|
50
|
+
### 📂 Alternatif: Instalasi Plugin Secara Manual (Opsional)
|
|
51
|
+
|
|
52
|
+
Jika Anda **tidak** menggunakan skrip installer otomatis di atas (misalnya hanya menambahkan server via `npx` di klien AI), pasang file plugin Roblox Studio secara manual:
|
|
53
|
+
1. Ambil file `nvstudio_mcp.rbxmx` dari folder [studio-plugin/nvstudio_mcp.rbxmx](file:///studio-plugin/nvstudio_mcp.rbxmx).
|
|
54
|
+
2. Pindahkan/salin file tersebut ke direktori plugin Roblox di komputer Anda:
|
|
55
|
+
- **Windows:** `%LOCALAPPDATA%\Roblox\Plugins` (atau `C:\Users\<Username>\AppData\Local\Roblox\Plugins`)
|
|
56
|
+
- **macOS:** `~/Documents/ROBLOX/Plugins`
|
|
57
|
+
3. Restart atau buka kembali Roblox Studio. Plugin akan muncul di tab **Plugins**.
|
|
42
58
|
|
|
43
|
-
|
|
59
|
+
---
|
|
44
60
|
|
|
45
|
-
|
|
61
|
+
## 🔌 Cara Menggunakan (Konfigurasi MCP Klien AI)
|
|
62
|
+
|
|
63
|
+
Jika Anda menggunakan AI Client lain seperti **Claude Desktop**, **Windsurf**, atau ingin menambahkan konfigurasi secara manual:
|
|
64
|
+
|
|
65
|
+
Tambahkan konfigurasi berikut ke file `mcp.json` Anda:
|
|
46
66
|
```json
|
|
47
67
|
{
|
|
48
68
|
"mcpServers": {
|
|
@@ -56,7 +76,15 @@ Salin konfigurasi ini:
|
|
|
56
76
|
}
|
|
57
77
|
}
|
|
58
78
|
```
|
|
59
|
-
*(
|
|
79
|
+
*(AI Anda akan selalu menjalankan versi terbaru dari server Bridge langsung dari NPM!)*
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 🖥️ Dashboard Visual & Fitur Pintar v2.0
|
|
84
|
+
|
|
85
|
+
- **Visual Dashboard Real-time:** Buka [http://localhost:3055](http://localhost:3055) di browser Anda untuk melihat monitor antrean perintah, log aktivitas AI, status koneksi Studio, dan statistik eksekusi secara visual.
|
|
86
|
+
- **Auto-Detect & Auto-Connect:** Plugin Roblox Studio otomatis menyambung ke server saat aktif dan kembali menunggu (*Waiting*) saat server mati tanpa interupsi manual.
|
|
87
|
+
- **Anti-Zombie Port Handling:** Tidak perlu khawatir error `EADDRINUSE`. Jika port `3055` tertahan oleh proses zombie akibat restart editor/IDE, server akan otomatis membersihkan port tersebut secara aman.
|
|
60
88
|
|
|
61
89
|
---
|
|
62
90
|
|
package/dist/build-plugin.js
CHANGED
|
@@ -39,7 +39,7 @@ function buildRbxmx() {
|
|
|
39
39
|
xml += `\t\t\t<bool name="DefinesCapabilities">false</bool>\n`;
|
|
40
40
|
xml += `\t\t\t<string name="Name">nvstudio_mcp</string>\n`;
|
|
41
41
|
xml += `\t\t\t<int64 name="SourceAssetId">-1</int64>\n`;
|
|
42
|
-
xml += `\t\t\t<
|
|
42
|
+
xml += `\t\t\t<BinaryString name="Tags"></BinaryString>\n`;
|
|
43
43
|
xml += `\t\t</Properties>\n`;
|
|
44
44
|
// Process files
|
|
45
45
|
for (const file of files) {
|
|
@@ -49,8 +49,9 @@ function buildRbxmx() {
|
|
|
49
49
|
// Main.server.lua is a Script, others are ModuleScripts
|
|
50
50
|
const isMain = name === 'Main.server';
|
|
51
51
|
const className = isMain ? 'Script' : 'ModuleScript';
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
const scriptName = isMain ? 'Main' : name;
|
|
53
|
+
// Use a clean referent
|
|
54
|
+
const referent = `RBX_${scriptName.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
|
54
55
|
xml += `\t\t<Item class="${className}" referent="${referent}">\n`;
|
|
55
56
|
xml += `\t\t\t<Properties>\n`;
|
|
56
57
|
xml += `\t\t\t\t<BinaryString name="AttributesSerialize"></BinaryString>\n`;
|
|
@@ -58,9 +59,9 @@ function buildRbxmx() {
|
|
|
58
59
|
xml += `\t\t\t\t<bool name="DefinesCapabilities">false</bool>\n`;
|
|
59
60
|
xml += `\t\t\t\t<bool name="Disabled">false</bool>\n`;
|
|
60
61
|
xml += `\t\t\t\t<Content name="LinkedSource"><null></null></Content>\n`;
|
|
61
|
-
xml += `\t\t\t\t<string name="Name">${
|
|
62
|
+
xml += `\t\t\t\t<string name="Name">${scriptName}</string>\n`;
|
|
62
63
|
xml += `\t\t\t\t<int64 name="SourceAssetId">-1</int64>\n`;
|
|
63
|
-
xml += `\t\t\t\t<
|
|
64
|
+
xml += `\t\t\t\t<BinaryString name="Tags"></BinaryString>\n`;
|
|
64
65
|
if (isMain) {
|
|
65
66
|
xml += `\t\t\t\t<token name="RunContext">0</token>\n`;
|
|
66
67
|
}
|
|
@@ -73,11 +74,7 @@ function buildRbxmx() {
|
|
|
73
74
|
}
|
|
74
75
|
// Close Folder
|
|
75
76
|
xml += `\t</Item>\n`;
|
|
76
|
-
//
|
|
77
|
-
xml += `\t<SharedStrings>\n`;
|
|
78
|
-
xml += `\t\t<SharedString md5="yuZpQdnvvUBOTYh1jqZ2cA=="></SharedString>\n`;
|
|
79
|
-
xml += `\t</SharedStrings>\n`;
|
|
80
|
-
// Close Roblox
|
|
77
|
+
// Close Roblox root (No SharedStrings block needed when all Tags are empty)
|
|
81
78
|
xml += `</roblox>\n`;
|
|
82
79
|
fs_1.default.writeFileSync(OUTPUT_FILE, xml, 'utf-8');
|
|
83
80
|
console.log(`[Build] Berhasil membuat ${OUTPUT_FILE}`);
|
|
@@ -111,5 +108,14 @@ function copyToRobloxPlugins() {
|
|
|
111
108
|
else {
|
|
112
109
|
console.log(`[Build] Platform ${process.platform} tidak didukung untuk auto-copy plugin.`);
|
|
113
110
|
}
|
|
111
|
+
// Also update ~/.nvstudio-mcp/studio-plugin/nvstudio_mcp.rbxmx if present
|
|
112
|
+
const homeClonePlugin = path_1.default.join(os_1.default.homedir(), '.nvstudio-mcp', 'studio-plugin', 'nvstudio_mcp.rbxmx');
|
|
113
|
+
if (fs_1.default.existsSync(path_1.default.dirname(homeClonePlugin))) {
|
|
114
|
+
try {
|
|
115
|
+
fs_1.default.copyFileSync(OUTPUT_FILE, homeClonePlugin);
|
|
116
|
+
console.log(`[Build] ✅ Berhasil memperbarui ${homeClonePlugin}`);
|
|
117
|
+
}
|
|
118
|
+
catch { }
|
|
119
|
+
}
|
|
114
120
|
}
|
|
115
121
|
buildRbxmx();
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adiholick/nvstudio-mcp",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.3",
|
|
4
4
|
"description": "Local Bridge Server MCP for Roblox Studio",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"nvstudio-mcp": "
|
|
7
|
+
"nvstudio-mcp": "dist/index.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
@@ -13,7 +13,7 @@ local ui = nil
|
|
|
13
13
|
|
|
14
14
|
-- Membangun Tombol Toolbar (Toggle)
|
|
15
15
|
local toolbar = plugin:CreateToolbar("NVStudio MCP")
|
|
16
|
-
local toggleBtn = toolbar:CreateButton("Dashboard", "Buka Dashboard NVStudio MCP", "rbxassetid://82696893597722")
|
|
16
|
+
local toggleBtn = toolbar:CreateButton("Dashboard", "Buka Dashboard NVStudio MCP", "rbxassetid://82696893597722", "NVStudio")
|
|
17
17
|
|
|
18
18
|
-- Global State & Context AI
|
|
19
19
|
local ctx = {
|
|
@@ -41,6 +41,14 @@ if uiModule then
|
|
|
41
41
|
ui:setAutoConnectState(autoConnect)
|
|
42
42
|
ui:setStatus("disconnected")
|
|
43
43
|
|
|
44
|
+
-- Sync state tombol toolbar dengan status widget
|
|
45
|
+
if ui.widget then
|
|
46
|
+
toggleBtn:SetActive(ui.widget.Enabled)
|
|
47
|
+
ui.widget:GetPropertyChangedSignal("Enabled"):Connect(function()
|
|
48
|
+
toggleBtn:SetActive(ui.widget.Enabled)
|
|
49
|
+
end)
|
|
50
|
+
end
|
|
51
|
+
|
|
44
52
|
-- Event Toggle GUI Panel
|
|
45
53
|
toggleBtn.Click:Connect(function()
|
|
46
54
|
ui:toggleVisibility()
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<bool name="DefinesCapabilities">false</bool>
|
|
9
9
|
<string name="Name">nvstudio_mcp</string>
|
|
10
10
|
<int64 name="SourceAssetId">-1</int64>
|
|
11
|
-
<
|
|
11
|
+
<BinaryString name="Tags"></BinaryString>
|
|
12
12
|
</Properties>
|
|
13
13
|
<Item class="ModuleScript" referent="RBX_create_instance">
|
|
14
14
|
<Properties>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<Content name="LinkedSource"><null></null></Content>
|
|
20
20
|
<string name="Name">create_instance</string>
|
|
21
21
|
<int64 name="SourceAssetId">-1</int64>
|
|
22
|
-
<
|
|
22
|
+
<BinaryString name="Tags"></BinaryString>
|
|
23
23
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
24
24
|
local success, config = pcall(function() return ctx.HttpService:JSONDecode(data) end)
|
|
25
25
|
if not success or not config.ClassName then
|
|
@@ -56,7 +56,7 @@ end
|
|
|
56
56
|
<Content name="LinkedSource"><null></null></Content>
|
|
57
57
|
<string name="Name">delete_instance</string>
|
|
58
58
|
<int64 name="SourceAssetId">-1</int64>
|
|
59
|
-
<
|
|
59
|
+
<BinaryString name="Tags"></BinaryString>
|
|
60
60
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
61
61
|
-- Guardrail: Cegah penghapusan Service utama
|
|
62
62
|
local protectedServices = {
|
|
@@ -100,7 +100,7 @@ end
|
|
|
100
100
|
<Content name="LinkedSource"><null></null></Content>
|
|
101
101
|
<string name="Name">execute_luau</string>
|
|
102
102
|
<int64 name="SourceAssetId">-1</int64>
|
|
103
|
-
<
|
|
103
|
+
<BinaryString name="Tags"></BinaryString>
|
|
104
104
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
105
105
|
local code = data
|
|
106
106
|
if not code or code == "" then
|
|
@@ -184,7 +184,7 @@ end
|
|
|
184
184
|
<Content name="LinkedSource"><null></null></Content>
|
|
185
185
|
<string name="Name">generate_terrain</string>
|
|
186
186
|
<int64 name="SourceAssetId">-1</int64>
|
|
187
|
-
<
|
|
187
|
+
<BinaryString name="Tags"></BinaryString>
|
|
188
188
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
189
189
|
local success, config = pcall(function() return ctx.HttpService:JSONDecode(data) end)
|
|
190
190
|
if not success or not config.Size or not config.Position or not config.Material then
|
|
@@ -220,7 +220,7 @@ end
|
|
|
220
220
|
<Content name="LinkedSource"><null></null></Content>
|
|
221
221
|
<string name="Name">get_children</string>
|
|
222
222
|
<int64 name="SourceAssetId">-1</int64>
|
|
223
|
-
<
|
|
223
|
+
<BinaryString name="Tags"></BinaryString>
|
|
224
224
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
225
225
|
local children = {}
|
|
226
226
|
for _, child in ipairs(targetInstance:GetChildren()) do
|
|
@@ -240,7 +240,7 @@ end
|
|
|
240
240
|
<Content name="LinkedSource"><null></null></Content>
|
|
241
241
|
<string name="Name">get_logs</string>
|
|
242
242
|
<int64 name="SourceAssetId">-1</int64>
|
|
243
|
-
<
|
|
243
|
+
<BinaryString name="Tags"></BinaryString>
|
|
244
244
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
245
245
|
if #ctx.recentLogs == 0 then
|
|
246
246
|
return { status = "success", result = {"Console kosong. Tidak ada error atau log terbaru."} }
|
|
@@ -260,7 +260,7 @@ end
|
|
|
260
260
|
<Content name="LinkedSource"><null></null></Content>
|
|
261
261
|
<string name="Name">get_properties</string>
|
|
262
262
|
<int64 name="SourceAssetId">-1</int64>
|
|
263
|
-
<
|
|
263
|
+
<BinaryString name="Tags"></BinaryString>
|
|
264
264
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
265
265
|
local CollectionService = game:GetService("CollectionService")
|
|
266
266
|
|
|
@@ -325,7 +325,7 @@ end
|
|
|
325
325
|
<Content name="LinkedSource"><null></null></Content>
|
|
326
326
|
<string name="Name">get_script_source</string>
|
|
327
327
|
<int64 name="SourceAssetId">-1</int64>
|
|
328
|
-
<
|
|
328
|
+
<BinaryString name="Tags"></BinaryString>
|
|
329
329
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
330
330
|
if targetInstance:IsA("LuaSourceContainer") then
|
|
331
331
|
return { status = "success", result = targetInstance.Source }
|
|
@@ -345,7 +345,7 @@ end
|
|
|
345
345
|
<Content name="LinkedSource"><null></null></Content>
|
|
346
346
|
<string name="Name">insert_asset</string>
|
|
347
347
|
<int64 name="SourceAssetId">-1</int64>
|
|
348
|
-
<
|
|
348
|
+
<BinaryString name="Tags"></BinaryString>
|
|
349
349
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
350
350
|
local InsertService = game:GetService("InsertService")
|
|
351
351
|
local assetId = tonumber(data)
|
|
@@ -367,16 +367,16 @@ end
|
|
|
367
367
|
]]></ProtectedString>
|
|
368
368
|
</Properties>
|
|
369
369
|
</Item>
|
|
370
|
-
<Item class="Script" referent="
|
|
370
|
+
<Item class="Script" referent="RBX_Main">
|
|
371
371
|
<Properties>
|
|
372
372
|
<BinaryString name="AttributesSerialize"></BinaryString>
|
|
373
373
|
<SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
|
|
374
374
|
<bool name="DefinesCapabilities">false</bool>
|
|
375
375
|
<bool name="Disabled">false</bool>
|
|
376
376
|
<Content name="LinkedSource"><null></null></Content>
|
|
377
|
-
<string name="Name">Main
|
|
377
|
+
<string name="Name">Main</string>
|
|
378
378
|
<int64 name="SourceAssetId">-1</int64>
|
|
379
|
-
<
|
|
379
|
+
<BinaryString name="Tags"></BinaryString>
|
|
380
380
|
<token name="RunContext">0</token>
|
|
381
381
|
<ProtectedString name="Source"><![CDATA[local HttpService = game:GetService("HttpService")
|
|
382
382
|
local LogService = game:GetService("LogService")
|
|
@@ -393,7 +393,7 @@ local ui = nil
|
|
|
393
393
|
|
|
394
394
|
-- Membangun Tombol Toolbar (Toggle)
|
|
395
395
|
local toolbar = plugin:CreateToolbar("NVStudio MCP")
|
|
396
|
-
local toggleBtn = toolbar:CreateButton("Dashboard", "Buka Dashboard NVStudio MCP", "rbxassetid://82696893597722")
|
|
396
|
+
local toggleBtn = toolbar:CreateButton("Dashboard", "Buka Dashboard NVStudio MCP", "rbxassetid://82696893597722", "NVStudio")
|
|
397
397
|
|
|
398
398
|
-- Global State & Context AI
|
|
399
399
|
local ctx = {
|
|
@@ -421,6 +421,14 @@ if uiModule then
|
|
|
421
421
|
ui:setAutoConnectState(autoConnect)
|
|
422
422
|
ui:setStatus("disconnected")
|
|
423
423
|
|
|
424
|
+
-- Sync state tombol toolbar dengan status widget
|
|
425
|
+
if ui.widget then
|
|
426
|
+
toggleBtn:SetActive(ui.widget.Enabled)
|
|
427
|
+
ui.widget:GetPropertyChangedSignal("Enabled"):Connect(function()
|
|
428
|
+
toggleBtn:SetActive(ui.widget.Enabled)
|
|
429
|
+
end)
|
|
430
|
+
end
|
|
431
|
+
|
|
424
432
|
-- Event Toggle GUI Panel
|
|
425
433
|
toggleBtn.Click:Connect(function()
|
|
426
434
|
ui:toggleVisibility()
|
|
@@ -692,7 +700,7 @@ end)
|
|
|
692
700
|
<Content name="LinkedSource"><null></null></Content>
|
|
693
701
|
<string name="Name">patch_script_source</string>
|
|
694
702
|
<int64 name="SourceAssetId">-1</int64>
|
|
695
|
-
<
|
|
703
|
+
<BinaryString name="Tags"></BinaryString>
|
|
696
704
|
<ProtectedString name="Source"><![CDATA[local HttpService = game:GetService("HttpService")
|
|
697
705
|
|
|
698
706
|
return function(targetInstance, data, ctx, targetPath)
|
|
@@ -802,7 +810,7 @@ end
|
|
|
802
810
|
<Content name="LinkedSource"><null></null></Content>
|
|
803
811
|
<string name="Name">rollback_script</string>
|
|
804
812
|
<int64 name="SourceAssetId">-1</int64>
|
|
805
|
-
<
|
|
813
|
+
<BinaryString name="Tags"></BinaryString>
|
|
806
814
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
807
815
|
if targetInstance:IsA("LuaSourceContainer") then
|
|
808
816
|
local prevSource = ctx.scriptHistory[targetPath]
|
|
@@ -828,7 +836,7 @@ end
|
|
|
828
836
|
<Content name="LinkedSource"><null></null></Content>
|
|
829
837
|
<string name="Name">script_grep</string>
|
|
830
838
|
<int64 name="SourceAssetId">-1</int64>
|
|
831
|
-
<
|
|
839
|
+
<BinaryString name="Tags"></BinaryString>
|
|
832
840
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
833
841
|
local query = tostring(data)
|
|
834
842
|
if not query or query == "" then
|
|
@@ -904,7 +912,7 @@ end
|
|
|
904
912
|
<Content name="LinkedSource"><null></null></Content>
|
|
905
913
|
<string name="Name">search_instance</string>
|
|
906
914
|
<int64 name="SourceAssetId">-1</int64>
|
|
907
|
-
<
|
|
915
|
+
<BinaryString name="Tags"></BinaryString>
|
|
908
916
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
909
917
|
local searchName = tostring(data)
|
|
910
918
|
local results = {}
|
|
@@ -937,7 +945,7 @@ end
|
|
|
937
945
|
<Content name="LinkedSource"><null></null></Content>
|
|
938
946
|
<string name="Name">ui_manager</string>
|
|
939
947
|
<int64 name="SourceAssetId">-1</int64>
|
|
940
|
-
<
|
|
948
|
+
<BinaryString name="Tags"></BinaryString>
|
|
941
949
|
<ProtectedString name="Source"><![CDATA[local UIManager = {}
|
|
942
950
|
local widget = nil
|
|
943
951
|
|
|
@@ -945,8 +953,8 @@ function UIManager.init(pluginInstance, studioId)
|
|
|
945
953
|
-- Membuat Widget Panel yang bisa di-dock (menempel)
|
|
946
954
|
local widgetInfo = DockWidgetPluginGuiInfo.new(
|
|
947
955
|
Enum.InitialDockState.Right,
|
|
948
|
-
|
|
949
|
-
false, --
|
|
956
|
+
true, -- Initially visible on first install so user immediately sees the dashboard
|
|
957
|
+
false, -- Don't override user's saved state on subsequent launches
|
|
950
958
|
380, -- Default width
|
|
951
959
|
520, -- Default height
|
|
952
960
|
280, -- Min width
|
|
@@ -1393,7 +1401,7 @@ return UIManager
|
|
|
1393
1401
|
<Content name="LinkedSource"><null></null></Content>
|
|
1394
1402
|
<string name="Name">update_script_source</string>
|
|
1395
1403
|
<int64 name="SourceAssetId">-1</int64>
|
|
1396
|
-
<
|
|
1404
|
+
<BinaryString name="Tags"></BinaryString>
|
|
1397
1405
|
<ProtectedString name="Source"><![CDATA[return function(targetInstance, data, ctx, targetPath)
|
|
1398
1406
|
if targetInstance:IsA("LuaSourceContainer") then
|
|
1399
1407
|
local newCode = data or ""
|
|
@@ -1414,7 +1422,4 @@ end
|
|
|
1414
1422
|
</Properties>
|
|
1415
1423
|
</Item>
|
|
1416
1424
|
</Item>
|
|
1417
|
-
<SharedStrings>
|
|
1418
|
-
<SharedString md5="yuZpQdnvvUBOTYh1jqZ2cA=="></SharedString>
|
|
1419
|
-
</SharedStrings>
|
|
1420
1425
|
</roblox>
|
|
@@ -5,8 +5,8 @@ function UIManager.init(pluginInstance, studioId)
|
|
|
5
5
|
-- Membuat Widget Panel yang bisa di-dock (menempel)
|
|
6
6
|
local widgetInfo = DockWidgetPluginGuiInfo.new(
|
|
7
7
|
Enum.InitialDockState.Right,
|
|
8
|
-
|
|
9
|
-
false, --
|
|
8
|
+
true, -- Initially visible on first install so user immediately sees the dashboard
|
|
9
|
+
false, -- Don't override user's saved state on subsequent launches
|
|
10
10
|
380, -- Default width
|
|
11
11
|
520, -- Default height
|
|
12
12
|
280, -- Min width
|