@el4cteo/rbx-studio-mcp 0.6.1 → 0.6.7

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 (75) hide show
  1. package/README.md +28 -2
  2. package/dist/bridge/console.js +182 -0
  3. package/dist/bridge/console.js.map +1 -1
  4. package/dist/index.js +8 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/cloudassets.js +233 -0
  7. package/dist/lib/cloudassets.js.map +1 -0
  8. package/dist/lib/credentials.js +180 -0
  9. package/dist/lib/credentials.js.map +1 -0
  10. package/dist/lib/livedata.js +325 -0
  11. package/dist/lib/livedata.js.map +1 -0
  12. package/dist/lib/liveluau.js +83 -0
  13. package/dist/lib/liveluau.js.map +1 -0
  14. package/dist/lib/liveops.js +358 -0
  15. package/dist/lib/liveops.js.map +1 -0
  16. package/dist/lib/opencloud.js +235 -0
  17. package/dist/lib/opencloud.js.map +1 -0
  18. package/dist/tools/anim.js +159 -0
  19. package/dist/tools/anim.js.map +1 -0
  20. package/dist/tools/audio.js +96 -0
  21. package/dist/tools/audio.js.map +1 -0
  22. package/dist/tools/character.js +95 -5
  23. package/dist/tools/character.js.map +1 -1
  24. package/dist/tools/data.js +292 -0
  25. package/dist/tools/data.js.map +1 -0
  26. package/dist/tools/device.js +77 -7
  27. package/dist/tools/device.js.map +1 -1
  28. package/dist/tools/discover.js +80 -4
  29. package/dist/tools/discover.js.map +1 -1
  30. package/dist/tools/exec.js +96 -2
  31. package/dist/tools/exec.js.map +1 -1
  32. package/dist/tools/input.js +35 -9
  33. package/dist/tools/input.js.map +1 -1
  34. package/dist/tools/perf.js +74 -7
  35. package/dist/tools/perf.js.map +1 -1
  36. package/dist/tools/scripts.js +162 -6
  37. package/dist/tools/scripts.js.map +1 -1
  38. package/dist/tools/spatial.js +135 -0
  39. package/dist/tools/spatial.js.map +1 -0
  40. package/dist/tools/universe.js +177 -0
  41. package/dist/tools/universe.js.map +1 -0
  42. package/dist/tools/upload.js +294 -0
  43. package/dist/tools/upload.js.map +1 -0
  44. package/dist/tools/world.js +675 -51
  45. package/dist/tools/world.js.map +1 -1
  46. package/package.json +2 -2
  47. package/plugin/src/Commands.luau +31 -7
  48. package/plugin/src/Config.luau +65 -65
  49. package/plugin/src/Console.luau +1909 -1843
  50. package/plugin/src/Emulation.luau +172 -0
  51. package/plugin/src/Phrase.luau +816 -618
  52. package/plugin/src/Png.luau +8 -4
  53. package/plugin/src/Prompt.luau +965 -961
  54. package/plugin/src/Secret.luau +86 -0
  55. package/plugin/src/Serialize.luau +440 -8
  56. package/plugin/src/Undo.luau +94 -6
  57. package/plugin/src/handlers/Anim.luau +897 -0
  58. package/plugin/src/handlers/Assets.luau +286 -2
  59. package/plugin/src/handlers/Audio.luau +411 -0
  60. package/plugin/src/handlers/Capture.luau +155 -20
  61. package/plugin/src/handlers/Character.luau +823 -361
  62. package/plugin/src/handlers/Data.luau +539 -0
  63. package/plugin/src/handlers/Device.luau +394 -139
  64. package/plugin/src/handlers/Discover.luau +685 -363
  65. package/plugin/src/handlers/Geometry.luau +722 -450
  66. package/plugin/src/handlers/Instances.luau +84 -4
  67. package/plugin/src/handlers/Perf.luau +227 -0
  68. package/plugin/src/handlers/Scripts.luau +673 -539
  69. package/plugin/src/handlers/Session.luau +3 -0
  70. package/plugin/src/handlers/Spatial.luau +334 -0
  71. package/plugin/src/handlers/Viewport.luau +268 -0
  72. package/plugin/src/handlers/World.luau +89 -15
  73. package/plugin/src/init.server.luau +9 -1
  74. package/scripts/build-plugin.mjs +20 -0
  75. package/scripts/check-plugin.mjs +171 -124
@@ -8,6 +8,12 @@
8
8
  shape. Emulation persists until it is switched off, which is exactly the kind
9
9
  of state that goes wrong quietly.
10
10
 
11
+ The network conditions Studio is shaping traffic with live here too. They are
12
+ the same kind of state for the same reason: set once, invisible on screen,
13
+ and they stay until something turns them off. A place that "feels laggy" with
14
+ a forgotten 400ms delay on it is exactly the bug this file exists to stop
15
+ people chasing.
16
+
11
17
  `StudioDeviceSimulatorService` is undocumented on its return shapes, so what
12
18
  is here was read off a live session. Two things are worth knowing:
13
19
 
@@ -21,8 +27,172 @@
21
27
 
22
28
  local StudioDeviceSimulatorService = game:GetService("StudioDeviceSimulatorService")
23
29
 
30
+ --[[
31
+ `NetworkSettings` is not a `game` service; it hangs off `settings()`.
32
+
33
+ `game:GetService("NetworkSettings")` throws outright, which is worth writing
34
+ down because every other service in this codebase is reached that way. The
35
+ traffic-shaping properties on it -- delay, jitter, loss, in each direction --
36
+ are PluginSecurity, so they are readable and writable here and nowhere near a
37
+ running game.
38
+
39
+ Guarded: it is reached through a `pcall` at every use rather than captured
40
+ once, because a Studio old enough to lack the properties should cost the
41
+ network feature, not the whole `device` tool.
42
+ ]]
43
+ local function networkSettings(): any?
44
+ local ok, service = pcall(function()
45
+ return (settings() :: any):GetService("NetworkSettings")
46
+ end)
47
+ if ok and service ~= nil then
48
+ return service
49
+ end
50
+ return nil
51
+ end
52
+
24
53
  local Emulation = {}
25
54
 
55
+ Emulation.networkSettings = networkSettings
56
+
57
+ --[[
58
+ The six traffic-shaping properties, in the order a person reads them.
59
+
60
+ Inbound is what the client receives and is what a laggy connection feels
61
+ like; outbound is what it sends, which is what makes a player's own actions
62
+ arrive late to everyone else. Both are shaped separately by Studio, so both
63
+ are carried separately here.
64
+ ]]
65
+ --[[
66
+ The memory ceiling this session set, if any.
67
+
68
+ Session-local by necessity: see the note in `Emulation.network`. A cap set by
69
+ Studio's own toolbar before the plugin loaded is invisible to this, which is
70
+ the honest failure -- reporting a cap that is not there was the alternative,
71
+ and it was worse.
72
+ ]]
73
+ local memoryCap: number? = nil
74
+
75
+ local NETWORK_FIELDS = {
76
+ { key = "inLatency", property = "InboundNetworkMinDelayMs", scale = 1 },
77
+ { key = "inJitter", property = "InboundNetworkJitterMs", scale = 1 },
78
+ { key = "inLoss", property = "InboundNetworkLossPercent", scale = 100 },
79
+ { key = "outLatency", property = "OutboundNetworkMinDelayMs", scale = 1 },
80
+ { key = "outJitter", property = "OutboundNetworkJitterMs", scale = 1 },
81
+ { key = "outLoss", property = "OutboundNetworkLossPercent", scale = 100 },
82
+ }
83
+
84
+ --[[
85
+ What the engine will actually accept, measured rather than assumed.
86
+
87
+ None of this is documented and all three of them bite. Writes outside these
88
+ ranges SUCCEED and are silently clamped, so a preset asking for 2% loss was
89
+ reporting 0.5 back and the only way to notice was to read the value again --
90
+ which is how this was found.
91
+
92
+ * Loss is a FRACTION, despite `LossPercent` in the name: it tops out at 0.5,
93
+ and 0.5 is half the packets, not half a percent. Everything above this
94
+ layer speaks in percent because that is what a person means by "2% loss",
95
+ so the conversion happens at the edges -- `scale` above on the way out, and
96
+ `LOSS_LIMIT` on the way in.
97
+ * Delay and jitter both stop at 1000ms. A second of latency is already past
98
+ anything a real connection does, so this costs nothing but honesty.
99
+ ]]
100
+ local LOSS_LIMIT = 0.5
101
+ local DELAY_LIMIT = 1000
102
+
103
+ Emulation.LOSS_LIMIT_PERCENT = LOSS_LIMIT * 100
104
+ Emulation.DELAY_LIMIT = DELAY_LIMIT
105
+
106
+ --[[
107
+ What Studio is currently doing to network traffic.
108
+
109
+ `shaping` is the field callers should branch on: every value being zero is
110
+ the normal, un-emulated state, and reporting six zeroes without saying so
111
+ makes "is anything on" a question the caller has to work out for itself.
112
+ ]]
113
+ function Emulation.network(): { [string]: any }
114
+ local service = networkSettings()
115
+ if service == nil then
116
+ return { available = false, shaping = false }
117
+ end
118
+
119
+ local state: { [string]: any } = { available = true }
120
+ local shaping = false
121
+ for _, field in NETWORK_FIELDS do
122
+ local ok, value = pcall(function()
123
+ return (service :: any)[field.property]
124
+ end)
125
+ local number = if ok then tonumber(value) or 0 else 0
126
+ --[[
127
+ Scaled into the caller's units, then rounded to two places. These are
128
+ 32-bit floats: 2% loss is stored as 0.02 and reads back as
129
+ 0.019999999552965164, and reporting that instead of 2 makes a
130
+ perfectly applied setting look like a failed one.
131
+ ]]
132
+ number *= field.scale
133
+ state[field.key] = math.round(number * 100) / 100
134
+ if number > 0 then
135
+ shaping = true
136
+ end
137
+ end
138
+
139
+ --[[
140
+ Reported, but deliberately not counted as shaping.
141
+
142
+ `EmulatedTotalMemoryInMB` does not read back 0 when nothing is emulated:
143
+ it answers with the machine's real memory -- measured, 16159 on the
144
+ session this was written against. Treating "greater than zero" as a cap
145
+ therefore declared every untouched Studio to be emulating a low-memory
146
+ device, and `studio_status` told the agent traffic was being degraded on
147
+ a session where nothing had ever been set.
148
+
149
+ There is no read that distinguishes a cap from the true figure, so the
150
+ cap is remembered instead, by the one thing that sets it.
151
+ ]]
152
+ local okMemory, memory = pcall(function()
153
+ return (service :: any).EmulatedTotalMemoryInMB
154
+ end)
155
+ if okMemory then
156
+ state.memoryMB = math.floor(tonumber(memory) or 0)
157
+ end
158
+
159
+ if memoryCap ~= nil and memoryCap > 0 then
160
+ state.memoryCapMB = memoryCap
161
+ shaping = true
162
+ end
163
+
164
+ state.shaping = shaping
165
+ return state
166
+ end
167
+
168
+ --[[
169
+ Records the memory ceiling this session asked for.
170
+
171
+ Held here rather than in the handler because `network` writes it and
172
+ `Emulation.network` reports it, and a value those two disagree about is worse
173
+ than no value at all. nil or 0 means no cap.
174
+ ]]
175
+ function Emulation.setMemoryCap(megabytes: number?)
176
+ memoryCap = if megabytes ~= nil and megabytes > 0 then megabytes else nil
177
+ end
178
+
179
+ --[[
180
+ The short form for `studio_status`, or nil when traffic is untouched.
181
+
182
+ Separate from the device summary rather than folded into it: a session can be
183
+ shaping traffic without emulating a device, and the device summary returns
184
+ nil in exactly that case.
185
+ ]]
186
+ function Emulation.networkSummary(): { [string]: any }?
187
+ local state = Emulation.network()
188
+ if state.shaping ~= true then
189
+ return nil
190
+ end
191
+ state.note = 'Studio is degrading network traffic on purpose. `device op="network" '
192
+ .. 'preset="clear"` restores it.'
193
+ return state
194
+ end
195
+
26
196
  --[[
27
197
  The resolution as it actually appears, rather than as the panel is specified.
28
198
 
@@ -128,6 +298,8 @@ function Emulation.state(): { [string]: any }
128
298
  state.scalingMode = tostring(scaling)
129
299
  end
130
300
 
301
+ state.network = Emulation.network()
302
+
131
303
  return state
132
304
  end
133
305