@el4cteo/rbx-studio-mcp 0.1.5 → 0.2.0
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 +217 -250
- package/dist/bridge/server.js +4 -0
- package/dist/bridge/server.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/errors.js +5 -3
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/protocol.js +23 -0
- package/dist/lib/protocol.js.map +1 -1
- package/dist/tools/discover.js +7 -1
- package/dist/tools/discover.js.map +1 -1
- package/dist/tools/instances.js +9 -1
- package/dist/tools/instances.js.map +1 -1
- package/dist/tools/playtest.js +8 -1
- package/dist/tools/playtest.js.map +1 -1
- package/dist/tools/session.js +9 -4
- package/dist/tools/session.js.map +1 -1
- package/dist/tools/world.js +9 -3
- package/dist/tools/world.js.map +1 -1
- package/package.json +2 -2
- package/plugin/src/Config.luau +1 -1
- package/plugin/src/Net.luau +23 -1
- package/plugin/src/Phrase.luau +158 -5
- package/plugin/src/Transport.luau +6 -0
- package/plugin/src/handlers/Debug.luau +63 -6
- package/plugin/src/handlers/Geometry.luau +20 -1
- package/plugin/src/handlers/World.luau +19 -0
- package/scripts/test-bridge.mjs +1 -0
|
@@ -84,6 +84,35 @@ local overflow = 0
|
|
|
84
84
|
local installed = false
|
|
85
85
|
local installError: string? = nil
|
|
86
86
|
|
|
87
|
+
--[[
|
|
88
|
+
Which lines currently carry a breakpoint, per script.
|
|
89
|
+
|
|
90
|
+
`ScriptDebuggerService` exposes no way to list what is set -- `AddBreakpoint`
|
|
91
|
+
and `RemoveBreakpoint` are the whole surface, one line at a time -- so
|
|
92
|
+
"clear every breakpoint in this script" needs its own record of what this
|
|
93
|
+
module put there, or it cannot be done at all without either the caller
|
|
94
|
+
naming every line back or this file falling back to `ClearBreakpoints()`,
|
|
95
|
+
which takes the whole session's breakpoints with it, including ones set by
|
|
96
|
+
someone else sharing this Studio.
|
|
97
|
+
]]
|
|
98
|
+
local trackedBreakpoints: { [Instance]: { [number]: boolean } } = {}
|
|
99
|
+
|
|
100
|
+
local function track(target: Instance, line: number)
|
|
101
|
+
local lines = trackedBreakpoints[target]
|
|
102
|
+
if lines == nil then
|
|
103
|
+
lines = {}
|
|
104
|
+
trackedBreakpoints[target] = lines
|
|
105
|
+
end
|
|
106
|
+
lines[line] = true
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
local function untrack(target: Instance, line: number)
|
|
110
|
+
local lines = trackedBreakpoints[target]
|
|
111
|
+
if lines then
|
|
112
|
+
lines[line] = nil
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
87
116
|
--[[
|
|
88
117
|
Flattens whatever the service hands back.
|
|
89
118
|
|
|
@@ -309,6 +338,7 @@ function Debug.set(params: { [string]: any }): { [string]: any }
|
|
|
309
338
|
end)
|
|
310
339
|
|
|
311
340
|
if ok then
|
|
341
|
+
track(target, descriptor.Line)
|
|
312
342
|
table.insert(added, {
|
|
313
343
|
path = Paths.of(target),
|
|
314
344
|
line = descriptor.Line,
|
|
@@ -362,13 +392,39 @@ function Debug.clear(params: { [string]: any }): { [string]: any }
|
|
|
362
392
|
if typeof(path) == "string" and path ~= "" then
|
|
363
393
|
local target = Paths.resolve(path)
|
|
364
394
|
local line = tonumber(params.line)
|
|
365
|
-
|
|
366
|
-
|
|
395
|
+
|
|
396
|
+
if line ~= nil then
|
|
397
|
+
local ok, removed = pcall(function()
|
|
398
|
+
return service:RemoveBreakpoint(target, line)
|
|
399
|
+
end)
|
|
400
|
+
untrack(target, line)
|
|
401
|
+
return { removed = ok and removed == true, path = Paths.of(target), line = line }
|
|
367
402
|
end
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
403
|
+
|
|
404
|
+
--[[
|
|
405
|
+
`path` alone, no `line`: every breakpoint this module put in that
|
|
406
|
+
script. `ScriptDebuggerService` has no "list breakpoints in this
|
|
407
|
+
script" of its own -- only `AddBreakpoint`/`RemoveBreakpoint`, one
|
|
408
|
+
line at a time -- so `trackedBreakpoints` is what makes this
|
|
409
|
+
possible at all, and it is also the reason it can only remove what
|
|
410
|
+
this session set: a breakpoint another client or the user placed
|
|
411
|
+
by hand was never tracked here, and this cannot see it to touch it.
|
|
412
|
+
]]
|
|
413
|
+
local lines = trackedBreakpoints[target]
|
|
414
|
+
local removedLines: { number } = {}
|
|
415
|
+
if lines then
|
|
416
|
+
for lineNumber in lines do
|
|
417
|
+
local ok = pcall(function()
|
|
418
|
+
service:RemoveBreakpoint(target, lineNumber)
|
|
419
|
+
end)
|
|
420
|
+
if ok then
|
|
421
|
+
table.insert(removedLines, lineNumber)
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
trackedBreakpoints[target] = nil
|
|
425
|
+
end
|
|
426
|
+
table.sort(removedLines)
|
|
427
|
+
return { removed = #removedLines > 0, path = Paths.of(target), lines = removedLines }
|
|
372
428
|
end
|
|
373
429
|
|
|
374
430
|
local ok, err = pcall(function()
|
|
@@ -377,6 +433,7 @@ function Debug.clear(params: { [string]: any }): { [string]: any }
|
|
|
377
433
|
if not ok then
|
|
378
434
|
Dispatch.fail("REFUSED", string.format("ClearBreakpoints refused: %s", tostring(err)))
|
|
379
435
|
end
|
|
436
|
+
table.clear(trackedBreakpoints)
|
|
380
437
|
return { cleared = true }
|
|
381
438
|
end
|
|
382
439
|
|
|
@@ -138,7 +138,6 @@ function Geometry.combine(params: { [string]: any }): { [string]: any }
|
|
|
138
138
|
then (if #produced == 1 then params.name else string.format("%s%d", params.name, index))
|
|
139
139
|
else subject.Name
|
|
140
140
|
part.Parent = parent
|
|
141
|
-
table.insert(created, Paths.of(part))
|
|
142
141
|
end
|
|
143
142
|
|
|
144
143
|
-- Removing the inputs is opt-in, and only once the results exist: an
|
|
@@ -150,6 +149,26 @@ function Geometry.combine(params: { [string]: any }): { [string]: any }
|
|
|
150
149
|
part:Destroy()
|
|
151
150
|
end
|
|
152
151
|
end
|
|
152
|
+
|
|
153
|
+
--[[
|
|
154
|
+
Paths for the produced parts are read only now, after the originals
|
|
155
|
+
are gone rather than in the loop above that named and parented them.
|
|
156
|
+
|
|
157
|
+
A result keeps the subject's name by default, so for the entire
|
|
158
|
+
window before the destroy above runs, the new part and the subject
|
|
159
|
+
it was built from are two same-named siblings in the same parent --
|
|
160
|
+
and Paths.of correctly, but uselessly, disambiguates that with a
|
|
161
|
+
`[2]` suffix that stops being true the instant the destroy runs a
|
|
162
|
+
few lines later. The caller reads this path after the call returns,
|
|
163
|
+
by which point the disambiguation was already wrong. Reading it here
|
|
164
|
+
instead describes where the part actually is once nothing further
|
|
165
|
+
in this function is going to move or remove anything -- correct
|
|
166
|
+
whether or not `keepOriginals` left a real, permanent collision for
|
|
167
|
+
it to still be disambiguating.
|
|
168
|
+
]]
|
|
169
|
+
for _, part in produced do
|
|
170
|
+
table.insert(created, Paths.of(part))
|
|
171
|
+
end
|
|
153
172
|
end)
|
|
154
173
|
|
|
155
174
|
return { created = created, removed = removed, undoable = undoable }
|
|
@@ -147,6 +147,25 @@ function World.collision(params: { [string]: any }): { [string]: any }
|
|
|
147
147
|
return { group = name, assigned = #assigned, parts = assigned, undoable = undoable }
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
+
if action == "remove" then
|
|
151
|
+
--[[
|
|
152
|
+
Registering a group is one line and nothing here undid it: create,
|
|
153
|
+
assign and collidable all had a way back through the ordinary undo
|
|
154
|
+
stack, and this did not, because nothing called it at all. Over a
|
|
155
|
+
session that experiments -- try a group, decide against it -- that
|
|
156
|
+
leaves the place permanently carrying a group nobody wants, with no
|
|
157
|
+
way to remove it short of `execute_luau`. `UnregisterCollisionGroup`
|
|
158
|
+
has existed the whole time; it was just never wired up.
|
|
159
|
+
]]
|
|
160
|
+
local ok, err = pcall(function()
|
|
161
|
+
PhysicsService:UnregisterCollisionGroup(name)
|
|
162
|
+
end)
|
|
163
|
+
if not ok then
|
|
164
|
+
Dispatch.fail("COLLISION_FAILED", string.format("Could not remove %q: %s", name, tostring(err)))
|
|
165
|
+
end
|
|
166
|
+
return { group = name, removed = true }
|
|
167
|
+
end
|
|
168
|
+
|
|
150
169
|
if action == "collidable" then
|
|
151
170
|
local other = params.with
|
|
152
171
|
if typeof(other) ~= "string" or other == "" then
|