@chrrxs/robloxstudio-mcp 2.23.0 → 3.0.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/dist/index.js +1532 -4565
- package/package.json +6 -4
- package/studio-plugin/INSTALLATION.md +18 -14
- package/studio-plugin/MCPInspectorPlugin.rbxmx +203 -1959
- package/studio-plugin/MCPPlugin.rbxmx +203 -1959
- package/studio-plugin/src/modules/Communication.ts +16 -47
- package/studio-plugin/src/modules/Utils.ts +60 -2
- package/studio-plugin/src/modules/handlers/MetadataHandlers.ts +3 -261
- package/studio-plugin/src/modules/handlers/PropertyHandlers.ts +1 -130
- package/studio-plugin/src/modules/handlers/QueryHandlers.ts +9 -167
- package/studio-plugin/src/modules/handlers/ScriptHandlers.ts +64 -63
- package/studio-plugin/src/modules/handlers/TestHandlers.ts +13 -6
- package/studio-plugin/src/modules/handlers/BuildHandlers.ts +0 -481
- package/studio-plugin/src/modules/handlers/InstanceHandlers.ts +0 -380
|
@@ -778,11 +778,9 @@ local UI = TS.import(script, script.Parent, "UI")
|
|
|
778
778
|
local cleanupLegacyEditBridges = TS.import(script, script.Parent, "EvalBridges").cleanupLegacyEditBridges
|
|
779
779
|
local QueryHandlers = TS.import(script, script.Parent, "handlers", "QueryHandlers")
|
|
780
780
|
local PropertyHandlers = TS.import(script, script.Parent, "handlers", "PropertyHandlers")
|
|
781
|
-
local InstanceHandlers = TS.import(script, script.Parent, "handlers", "InstanceHandlers")
|
|
782
781
|
local ScriptHandlers = TS.import(script, script.Parent, "handlers", "ScriptHandlers")
|
|
783
782
|
local MetadataHandlers = TS.import(script, script.Parent, "handlers", "MetadataHandlers")
|
|
784
783
|
local TestHandlers = TS.import(script, script.Parent, "handlers", "TestHandlers")
|
|
785
|
-
local BuildHandlers = TS.import(script, script.Parent, "handlers", "BuildHandlers")
|
|
786
784
|
local AssetHandlers = TS.import(script, script.Parent, "handlers", "AssetHandlers")
|
|
787
785
|
local CaptureHandlers = TS.import(script, script.Parent, "handlers", "CaptureHandlers")
|
|
788
786
|
local InputHandlers = TS.import(script, script.Parent, "handlers", "InputHandlers")
|
|
@@ -873,45 +871,22 @@ local routeMap = {
|
|
|
873
871
|
["/api/file-tree"] = QueryHandlers.getFileTree,
|
|
874
872
|
["/api/search-files"] = QueryHandlers.searchFiles,
|
|
875
873
|
["/api/place-info"] = QueryHandlers.getPlaceInfo,
|
|
876
|
-
["/api/services"] = QueryHandlers.getServices,
|
|
877
874
|
["/api/search-objects"] = QueryHandlers.searchObjects,
|
|
878
875
|
["/api/instance-properties"] = QueryHandlers.getInstanceProperties,
|
|
879
|
-
["/api/instance-children"] = QueryHandlers.getInstanceChildren,
|
|
880
876
|
["/api/search-by-property"] = QueryHandlers.searchByProperty,
|
|
881
877
|
["/api/class-info"] = QueryHandlers.getClassInfo,
|
|
882
878
|
["/api/project-structure"] = QueryHandlers.getProjectStructure,
|
|
883
879
|
["/api/grep-scripts"] = QueryHandlers.grepScripts,
|
|
884
|
-
["/api/get-descendants"] = QueryHandlers.getDescendants,
|
|
885
|
-
["/api/compare-instances"] = QueryHandlers.compareInstances,
|
|
886
|
-
["/api/set-property"] = PropertyHandlers.setProperty,
|
|
887
880
|
["/api/set-properties"] = PropertyHandlers.setProperties,
|
|
888
|
-
["/api/mass-set-property"] = PropertyHandlers.massSetProperty,
|
|
889
|
-
["/api/mass-get-property"] = PropertyHandlers.massGetProperty,
|
|
890
|
-
["/api/create-object"] = InstanceHandlers.createObject,
|
|
891
|
-
["/api/mass-create-objects"] = InstanceHandlers.massCreateObjects,
|
|
892
|
-
["/api/mass-create-objects-with-properties"] = InstanceHandlers.massCreateObjects,
|
|
893
|
-
["/api/delete-object"] = InstanceHandlers.deleteObject,
|
|
894
|
-
["/api/smart-duplicate"] = InstanceHandlers.smartDuplicate,
|
|
895
|
-
["/api/mass-duplicate"] = InstanceHandlers.massDuplicate,
|
|
896
|
-
["/api/clone-object"] = InstanceHandlers.cloneObject,
|
|
897
881
|
["/api/get-script-source"] = ScriptHandlers.getScriptSource,
|
|
898
882
|
["/api/set-script-source"] = ScriptHandlers.setScriptSource,
|
|
899
883
|
["/api/edit-script-lines"] = ScriptHandlers.editScriptLines,
|
|
900
884
|
["/api/insert-script-lines"] = ScriptHandlers.insertScriptLines,
|
|
901
885
|
["/api/delete-script-lines"] = ScriptHandlers.deleteScriptLines,
|
|
902
|
-
["/api/set-attribute"] = MetadataHandlers.setAttribute,
|
|
903
886
|
["/api/get-attributes"] = MetadataHandlers.getAttributes,
|
|
904
|
-
["/api/delete-attribute"] = MetadataHandlers.deleteAttribute,
|
|
905
|
-
["/api/get-tags"] = MetadataHandlers.getTags,
|
|
906
|
-
["/api/add-tag"] = MetadataHandlers.addTag,
|
|
907
|
-
["/api/remove-tag"] = MetadataHandlers.removeTag,
|
|
908
|
-
["/api/get-tagged"] = MetadataHandlers.getTagged,
|
|
909
887
|
["/api/get-selection"] = MetadataHandlers.getSelection,
|
|
910
888
|
["/api/execute-luau"] = MetadataHandlers.executeLuau,
|
|
911
889
|
["/api/eval-runtime"] = EvalRuntimeHandlers.evalRuntime,
|
|
912
|
-
["/api/undo"] = MetadataHandlers.undo,
|
|
913
|
-
["/api/redo"] = MetadataHandlers.redo,
|
|
914
|
-
["/api/bulk-set-attributes"] = MetadataHandlers.bulkSetAttributes,
|
|
915
890
|
["/api/start-playtest"] = TestHandlers.startPlaytest,
|
|
916
891
|
["/api/stop-playtest"] = TestHandlers.stopPlaytest,
|
|
917
892
|
["/api/multiplayer-test-start"] = TestHandlers.multiplayerTestStart,
|
|
@@ -919,10 +894,6 @@ local routeMap = {
|
|
|
919
894
|
["/api/multiplayer-test-add-players"] = TestHandlers.multiplayerTestAddPlayers,
|
|
920
895
|
["/api/multiplayer-test-leave-client"] = TestHandlers.multiplayerTestLeaveClient,
|
|
921
896
|
["/api/multiplayer-test-end"] = TestHandlers.multiplayerTestEnd,
|
|
922
|
-
["/api/export-build"] = BuildHandlers.exportBuild,
|
|
923
|
-
["/api/import-build"] = BuildHandlers.importBuild,
|
|
924
|
-
["/api/import-scene"] = BuildHandlers.importScene,
|
|
925
|
-
["/api/search-materials"] = BuildHandlers.searchMaterials,
|
|
926
897
|
["/api/insert-asset"] = AssetHandlers.insertAsset,
|
|
927
898
|
["/api/preview-asset"] = AssetHandlers.previewAsset,
|
|
928
899
|
["/api/capture-screenshot"] = CaptureHandlers.captureScreenshot,
|
|
@@ -1550,9 +1521,9 @@ local function computeBridgeStamp()
|
|
|
1550
1521
|
for i = 1, #combined do
|
|
1551
1522
|
h = (h * 33 + (string.byte(combined, i))) % 2147483647
|
|
1552
1523
|
end
|
|
1553
|
-
-- "
|
|
1524
|
+
-- "3.0.0" is replaced with the package version at package time
|
|
1554
1525
|
-- (scripts/build-plugin.mjs injectVersion), so a release bump also restamps.
|
|
1555
|
-
return `{tostring(h)}-
|
|
1526
|
+
return `{tostring(h)}-3.0.0`
|
|
1556
1527
|
end
|
|
1557
1528
|
local BRIDGE_STAMP = computeBridgeStamp()
|
|
1558
1529
|
local function setSource(scriptInst, source)
|
|
@@ -2669,571 +2640,6 @@ return {
|
|
|
2669
2640
|
</Properties>
|
|
2670
2641
|
</Item>
|
|
2671
2642
|
<Item class="ModuleScript" referent="9">
|
|
2672
|
-
<Properties>
|
|
2673
|
-
<string name="Name">BuildHandlers</string>
|
|
2674
|
-
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
2675
|
-
local TS = require(script.Parent.Parent.Parent.include.RuntimeLib)
|
|
2676
|
-
local Utils = TS.import(script, script.Parent.Parent, "Utils")
|
|
2677
|
-
local Recording = TS.import(script, script.Parent.Parent, "Recording")
|
|
2678
|
-
local MaterialService = game:GetService("MaterialService")
|
|
2679
|
-
local _binding = Utils
|
|
2680
|
-
local getInstancePath = _binding.getInstancePath
|
|
2681
|
-
local getInstanceByPath = _binding.getInstanceByPath
|
|
2682
|
-
local _binding_1 = Recording
|
|
2683
|
-
local beginRecording = _binding_1.beginRecording
|
|
2684
|
-
local finishRecording = _binding_1.finishRecording
|
|
2685
|
-
local MATERIAL_BY_NAME = {}
|
|
2686
|
-
for _, enumItem in Enum.Material:GetEnumItems() do
|
|
2687
|
-
local _name = enumItem.Name
|
|
2688
|
-
MATERIAL_BY_NAME[_name] = enumItem
|
|
2689
|
-
end
|
|
2690
|
-
-- Shape class mapping
|
|
2691
|
-
local SHAPE_CLASSES = {
|
|
2692
|
-
Block = "Part",
|
|
2693
|
-
Wedge = "WedgePart",
|
|
2694
|
-
Cylinder = "Part",
|
|
2695
|
-
Ball = "Part",
|
|
2696
|
-
CornerWedge = "CornerWedgePart",
|
|
2697
|
-
}
|
|
2698
|
-
local PALETTE_KEYS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
2699
|
-
local function roundTo(n, decimals)
|
|
2700
|
-
local mult = 10 ^ decimals
|
|
2701
|
-
return math.round(n * mult) / mult
|
|
2702
|
-
end
|
|
2703
|
-
local function encodePaletteKey(index)
|
|
2704
|
-
local base = #PALETTE_KEYS
|
|
2705
|
-
local value = math.floor(index) + 1
|
|
2706
|
-
local encoded = ""
|
|
2707
|
-
while value > 0 do
|
|
2708
|
-
value -= 1
|
|
2709
|
-
local digit = value % base
|
|
2710
|
-
local _arg0 = digit + 1
|
|
2711
|
-
local _arg1 = digit + 1
|
|
2712
|
-
encoded = string.sub(PALETTE_KEYS, _arg0, _arg1) .. encoded
|
|
2713
|
-
value = math.floor(value / base)
|
|
2714
|
-
end
|
|
2715
|
-
return encoded
|
|
2716
|
-
end
|
|
2717
|
-
local function getVariantName(part)
|
|
2718
|
-
local variantName = part.MaterialVariant
|
|
2719
|
-
if variantName == "" then
|
|
2720
|
-
local ok, variantAttr = pcall(function()
|
|
2721
|
-
return part:GetAttribute("MaterialVariant")
|
|
2722
|
-
end)
|
|
2723
|
-
if ok and type(variantAttr) == "string" then
|
|
2724
|
-
variantName = variantAttr
|
|
2725
|
-
end
|
|
2726
|
-
end
|
|
2727
|
-
return variantName
|
|
2728
|
-
end
|
|
2729
|
-
local function exportBuild(requestData)
|
|
2730
|
-
local instancePath = requestData.instancePath
|
|
2731
|
-
local outputId = requestData.outputId
|
|
2732
|
-
local _condition = (requestData.style)
|
|
2733
|
-
if _condition == nil then
|
|
2734
|
-
_condition = "misc"
|
|
2735
|
-
end
|
|
2736
|
-
local style = _condition
|
|
2737
|
-
if not (instancePath ~= "" and instancePath) then
|
|
2738
|
-
return {
|
|
2739
|
-
error = "Instance path is required",
|
|
2740
|
-
}
|
|
2741
|
-
end
|
|
2742
|
-
local instance = getInstanceByPath(instancePath)
|
|
2743
|
-
if not instance then
|
|
2744
|
-
return {
|
|
2745
|
-
error = `Instance not found: {instancePath}`,
|
|
2746
|
-
}
|
|
2747
|
-
end
|
|
2748
|
-
if not instance:IsA("Model") and not instance:IsA("Folder") then
|
|
2749
|
-
return {
|
|
2750
|
-
error = "Instance must be a Model or Folder",
|
|
2751
|
-
}
|
|
2752
|
-
end
|
|
2753
|
-
local success, result = pcall(function()
|
|
2754
|
-
local descendants = instance:GetDescendants()
|
|
2755
|
-
local baseParts = {}
|
|
2756
|
-
for _, desc in descendants do
|
|
2757
|
-
if desc:IsA("BasePart") then
|
|
2758
|
-
table.insert(baseParts, desc)
|
|
2759
|
-
end
|
|
2760
|
-
end
|
|
2761
|
-
if #baseParts == 0 then
|
|
2762
|
-
return {
|
|
2763
|
-
error = "No BaseParts found in instance",
|
|
2764
|
-
}
|
|
2765
|
-
end
|
|
2766
|
-
-- Compute bounding box center
|
|
2767
|
-
local minX = math.huge
|
|
2768
|
-
local minY = math.huge
|
|
2769
|
-
local minZ = math.huge
|
|
2770
|
-
local maxX = -math.huge
|
|
2771
|
-
local maxY = -math.huge
|
|
2772
|
-
local maxZ = -math.huge
|
|
2773
|
-
for _, part in baseParts do
|
|
2774
|
-
local pos = part.Position
|
|
2775
|
-
local sz = part.Size
|
|
2776
|
-
local halfX = sz.X / 2
|
|
2777
|
-
local halfY = sz.Y / 2
|
|
2778
|
-
local halfZ = sz.Z / 2
|
|
2779
|
-
minX = math.min(minX, pos.X - halfX)
|
|
2780
|
-
minY = math.min(minY, pos.Y - halfY)
|
|
2781
|
-
minZ = math.min(minZ, pos.Z - halfZ)
|
|
2782
|
-
maxX = math.max(maxX, pos.X + halfX)
|
|
2783
|
-
maxY = math.max(maxY, pos.Y + halfY)
|
|
2784
|
-
maxZ = math.max(maxZ, pos.Z + halfZ)
|
|
2785
|
-
end
|
|
2786
|
-
local centerX = (minX + maxX) / 2
|
|
2787
|
-
local centerY = minY
|
|
2788
|
-
local centerZ = (minZ + maxZ) / 2
|
|
2789
|
-
local boundsX = roundTo(maxX - minX, 1)
|
|
2790
|
-
local boundsY = roundTo(maxY - minY, 1)
|
|
2791
|
-
local boundsZ = roundTo(maxZ - minZ, 1)
|
|
2792
|
-
-- Build palette from unique (BrickColor, Material, MaterialVariant?) combos
|
|
2793
|
-
local paletteMap = {}
|
|
2794
|
-
local palette = {}
|
|
2795
|
-
local keyIndex = 0
|
|
2796
|
-
for _, part in baseParts do
|
|
2797
|
-
local colorName = part.BrickColor.Name
|
|
2798
|
-
local materialName = part.Material.Name
|
|
2799
|
-
local variantName = getVariantName(part)
|
|
2800
|
-
local combo = if variantName ~= "" then `{colorName}|{materialName}|{variantName}` else `{colorName}|{materialName}`
|
|
2801
|
-
if not (paletteMap[combo] ~= nil) then
|
|
2802
|
-
local key = encodePaletteKey(keyIndex)
|
|
2803
|
-
keyIndex += 1
|
|
2804
|
-
paletteMap[combo] = key
|
|
2805
|
-
if variantName ~= "" then
|
|
2806
|
-
palette[key] = { colorName, materialName, variantName }
|
|
2807
|
-
else
|
|
2808
|
-
palette[key] = { colorName, materialName }
|
|
2809
|
-
end
|
|
2810
|
-
end
|
|
2811
|
-
end
|
|
2812
|
-
-- Build compact part arrays
|
|
2813
|
-
local parts = {}
|
|
2814
|
-
for _, part in baseParts do
|
|
2815
|
-
local pos = part.Position
|
|
2816
|
-
local orient = part.Orientation
|
|
2817
|
-
local sz = part.Size
|
|
2818
|
-
local colorName = part.BrickColor.Name
|
|
2819
|
-
local materialName = part.Material.Name
|
|
2820
|
-
local variantName = getVariantName(part)
|
|
2821
|
-
local combo = if variantName ~= "" then `{colorName}|{materialName}|{variantName}` else `{colorName}|{materialName}`
|
|
2822
|
-
local _condition_1 = paletteMap[combo]
|
|
2823
|
-
if _condition_1 == nil then
|
|
2824
|
-
_condition_1 = "a"
|
|
2825
|
-
end
|
|
2826
|
-
local paletteKey = _condition_1
|
|
2827
|
-
-- Relative position to center
|
|
2828
|
-
local relX = roundTo(pos.X - centerX, 1)
|
|
2829
|
-
local relY = roundTo(pos.Y - centerY, 1)
|
|
2830
|
-
local relZ = roundTo(pos.Z - centerZ, 1)
|
|
2831
|
-
local sizeX = roundTo(sz.X, 1)
|
|
2832
|
-
local sizeY = roundTo(sz.Y, 1)
|
|
2833
|
-
local sizeZ = roundTo(sz.Z, 1)
|
|
2834
|
-
local rotX = roundTo(orient.X, 1)
|
|
2835
|
-
local rotY = roundTo(orient.Y, 1)
|
|
2836
|
-
local rotZ = roundTo(orient.Z, 1)
|
|
2837
|
-
-- Determine shape
|
|
2838
|
-
local shape = "Block"
|
|
2839
|
-
if part:IsA("WedgePart") then
|
|
2840
|
-
shape = "Wedge"
|
|
2841
|
-
elseif part:IsA("CornerWedgePart") then
|
|
2842
|
-
shape = "CornerWedge"
|
|
2843
|
-
elseif part:IsA("Part") then
|
|
2844
|
-
local p = part
|
|
2845
|
-
if p.Shape == Enum.PartType.Cylinder then
|
|
2846
|
-
shape = "Cylinder"
|
|
2847
|
-
elseif p.Shape == Enum.PartType.Ball then
|
|
2848
|
-
shape = "Ball"
|
|
2849
|
-
end
|
|
2850
|
-
end
|
|
2851
|
-
-- Build part array with optional trailing fields
|
|
2852
|
-
local hasTransparency = part.Transparency > 0
|
|
2853
|
-
local hasShape = shape ~= "Block"
|
|
2854
|
-
local partArr
|
|
2855
|
-
if hasTransparency then
|
|
2856
|
-
partArr = { relX, relY, relZ, sizeX, sizeY, sizeZ, rotX, rotY, rotZ, paletteKey, if hasShape then shape else "Block", roundTo(part.Transparency, 2) }
|
|
2857
|
-
elseif hasShape then
|
|
2858
|
-
partArr = { relX, relY, relZ, sizeX, sizeY, sizeZ, rotX, rotY, rotZ, paletteKey, shape }
|
|
2859
|
-
else
|
|
2860
|
-
partArr = { relX, relY, relZ, sizeX, sizeY, sizeZ, rotX, rotY, rotZ, paletteKey }
|
|
2861
|
-
end
|
|
2862
|
-
local _partArr = partArr
|
|
2863
|
-
table.insert(parts, _partArr)
|
|
2864
|
-
end
|
|
2865
|
-
local _condition_1 = outputId
|
|
2866
|
-
if _condition_1 == nil then
|
|
2867
|
-
_condition_1 = `{style}/{(string.gsub(string.lower(instance.Name), " ", "_"))}`
|
|
2868
|
-
end
|
|
2869
|
-
local buildId = _condition_1
|
|
2870
|
-
return {
|
|
2871
|
-
success = true,
|
|
2872
|
-
buildData = {
|
|
2873
|
-
id = buildId,
|
|
2874
|
-
style = style,
|
|
2875
|
-
bounds = { boundsX, boundsY, boundsZ },
|
|
2876
|
-
palette = palette,
|
|
2877
|
-
parts = parts,
|
|
2878
|
-
},
|
|
2879
|
-
}
|
|
2880
|
-
end)
|
|
2881
|
-
if success and result then
|
|
2882
|
-
return result
|
|
2883
|
-
else
|
|
2884
|
-
return {
|
|
2885
|
-
error = `Failed to export build: {result}`,
|
|
2886
|
-
}
|
|
2887
|
-
end
|
|
2888
|
-
end
|
|
2889
|
-
local function importBuild(requestData)
|
|
2890
|
-
local buildData = requestData.buildData
|
|
2891
|
-
local targetPath = requestData.targetPath
|
|
2892
|
-
local positionOffset = (requestData.position) or { 0, 0, 0 }
|
|
2893
|
-
if not buildData or not (targetPath ~= "" and targetPath) then
|
|
2894
|
-
return {
|
|
2895
|
-
error = "buildData and targetPath are required",
|
|
2896
|
-
}
|
|
2897
|
-
end
|
|
2898
|
-
local parentInstance = getInstanceByPath(targetPath)
|
|
2899
|
-
if not parentInstance then
|
|
2900
|
-
return {
|
|
2901
|
-
error = `Target not found: {targetPath}`,
|
|
2902
|
-
}
|
|
2903
|
-
end
|
|
2904
|
-
local recordingId = beginRecording("Import build")
|
|
2905
|
-
local success, result = pcall(function()
|
|
2906
|
-
local palette = buildData.palette
|
|
2907
|
-
local parts = buildData.parts
|
|
2908
|
-
local _condition = (buildData.id)
|
|
2909
|
-
if _condition == nil then
|
|
2910
|
-
_condition = "imported_build"
|
|
2911
|
-
end
|
|
2912
|
-
local buildId = _condition
|
|
2913
|
-
-- Create model container
|
|
2914
|
-
local model = Instance.new("Model")
|
|
2915
|
-
local _condition_1 = (string.match(buildId, "[^/]+$"))
|
|
2916
|
-
if _condition_1 == nil then
|
|
2917
|
-
_condition_1 = buildId
|
|
2918
|
-
end
|
|
2919
|
-
model.Name = _condition_1
|
|
2920
|
-
local partCount = 0
|
|
2921
|
-
for _, partArr in parts do
|
|
2922
|
-
local _exp = (partArr[1])
|
|
2923
|
-
local _condition_2 = positionOffset[1]
|
|
2924
|
-
if _condition_2 == nil then
|
|
2925
|
-
_condition_2 = 0
|
|
2926
|
-
end
|
|
2927
|
-
local posX = _exp + _condition_2
|
|
2928
|
-
local _exp_1 = (partArr[2])
|
|
2929
|
-
local _condition_3 = positionOffset[2]
|
|
2930
|
-
if _condition_3 == nil then
|
|
2931
|
-
_condition_3 = 0
|
|
2932
|
-
end
|
|
2933
|
-
local posY = _exp_1 + _condition_3
|
|
2934
|
-
local _exp_2 = (partArr[3])
|
|
2935
|
-
local _condition_4 = positionOffset[3]
|
|
2936
|
-
if _condition_4 == nil then
|
|
2937
|
-
_condition_4 = 0
|
|
2938
|
-
end
|
|
2939
|
-
local posZ = _exp_2 + _condition_4
|
|
2940
|
-
local sizeX = partArr[4]
|
|
2941
|
-
local sizeY = partArr[5]
|
|
2942
|
-
local sizeZ = partArr[6]
|
|
2943
|
-
local rotX = partArr[7]
|
|
2944
|
-
local rotY = partArr[8]
|
|
2945
|
-
local rotZ = partArr[9]
|
|
2946
|
-
local paletteKey = partArr[10]
|
|
2947
|
-
local _condition_5 = (partArr[11])
|
|
2948
|
-
if _condition_5 == nil then
|
|
2949
|
-
_condition_5 = "Block"
|
|
2950
|
-
end
|
|
2951
|
-
local shape = _condition_5
|
|
2952
|
-
local _condition_6 = (partArr[12])
|
|
2953
|
-
if _condition_6 == nil then
|
|
2954
|
-
_condition_6 = 0
|
|
2955
|
-
end
|
|
2956
|
-
local transparency = _condition_6
|
|
2957
|
-
-- Determine class from shape
|
|
2958
|
-
local _condition_7 = SHAPE_CLASSES[shape]
|
|
2959
|
-
if _condition_7 == nil then
|
|
2960
|
-
_condition_7 = "Part"
|
|
2961
|
-
end
|
|
2962
|
-
local className = _condition_7
|
|
2963
|
-
local part = Instance.new(className)
|
|
2964
|
-
-- Set shape for Part instances with non-Block shapes
|
|
2965
|
-
if className == "Part" and shape ~= "Block" then
|
|
2966
|
-
if shape == "Cylinder" then
|
|
2967
|
-
part.Shape = Enum.PartType.Cylinder
|
|
2968
|
-
elseif shape == "Ball" then
|
|
2969
|
-
part.Shape = Enum.PartType.Ball
|
|
2970
|
-
end
|
|
2971
|
-
end
|
|
2972
|
-
part.Size = Vector3.new(sizeX, sizeY, sizeZ)
|
|
2973
|
-
part.Position = Vector3.new(posX, posY, posZ)
|
|
2974
|
-
part.Orientation = Vector3.new(rotX, rotY, rotZ)
|
|
2975
|
-
part.Anchored = true
|
|
2976
|
-
if transparency > 0 then
|
|
2977
|
-
part.Transparency = transparency
|
|
2978
|
-
end
|
|
2979
|
-
-- Apply palette
|
|
2980
|
-
local paletteEntry = palette[paletteKey]
|
|
2981
|
-
if paletteEntry then
|
|
2982
|
-
local _binding_2 = paletteEntry
|
|
2983
|
-
local colorName = _binding_2[1]
|
|
2984
|
-
local materialName = _binding_2[2]
|
|
2985
|
-
local variantName = _binding_2[3]
|
|
2986
|
-
pcall(function()
|
|
2987
|
-
part.BrickColor = BrickColor.new(colorName)
|
|
2988
|
-
end)
|
|
2989
|
-
pcall(function()
|
|
2990
|
-
local mat = MATERIAL_BY_NAME[materialName]
|
|
2991
|
-
if mat ~= nil then
|
|
2992
|
-
part.Material = mat
|
|
2993
|
-
end
|
|
2994
|
-
end)
|
|
2995
|
-
-- Apply MaterialVariant if specified
|
|
2996
|
-
if variantName ~= nil and variantName ~= "" then
|
|
2997
|
-
pcall(function()
|
|
2998
|
-
part.MaterialVariant = variantName
|
|
2999
|
-
end)
|
|
3000
|
-
end
|
|
3001
|
-
end
|
|
3002
|
-
part.Parent = model
|
|
3003
|
-
partCount += 1
|
|
3004
|
-
end
|
|
3005
|
-
model.Parent = parentInstance
|
|
3006
|
-
return {
|
|
3007
|
-
success = true,
|
|
3008
|
-
partCount = partCount,
|
|
3009
|
-
modelPath = getInstancePath(model),
|
|
3010
|
-
}
|
|
3011
|
-
end)
|
|
3012
|
-
if success and result then
|
|
3013
|
-
finishRecording(recordingId, true)
|
|
3014
|
-
return result
|
|
3015
|
-
else
|
|
3016
|
-
finishRecording(recordingId, false)
|
|
3017
|
-
return {
|
|
3018
|
-
error = `Failed to import build: {result}`,
|
|
3019
|
-
}
|
|
3020
|
-
end
|
|
3021
|
-
end
|
|
3022
|
-
local function importScene(requestData)
|
|
3023
|
-
local expandedBuilds = requestData.expandedBuilds
|
|
3024
|
-
local _condition = (requestData.targetPath)
|
|
3025
|
-
if _condition == nil then
|
|
3026
|
-
_condition = "game.Workspace"
|
|
3027
|
-
end
|
|
3028
|
-
local targetPath = _condition
|
|
3029
|
-
if not expandedBuilds or not (type(expandedBuilds) == "table") or #expandedBuilds == 0 then
|
|
3030
|
-
return {
|
|
3031
|
-
error = "expandedBuilds array is required",
|
|
3032
|
-
}
|
|
3033
|
-
end
|
|
3034
|
-
local parentInstance = getInstanceByPath(targetPath)
|
|
3035
|
-
if not parentInstance then
|
|
3036
|
-
return {
|
|
3037
|
-
error = `Target not found: {targetPath}`,
|
|
3038
|
-
}
|
|
3039
|
-
end
|
|
3040
|
-
local recordingId = beginRecording("Import scene")
|
|
3041
|
-
local success, result = pcall(function()
|
|
3042
|
-
local modelCount = 0
|
|
3043
|
-
local totalParts = 0
|
|
3044
|
-
local models = {}
|
|
3045
|
-
for _, entry in expandedBuilds do
|
|
3046
|
-
local buildData = entry.buildData
|
|
3047
|
-
local position = (entry.position) or { 0, 0, 0 }
|
|
3048
|
-
local rotation = (entry.rotation) or { 0, 0, 0 }
|
|
3049
|
-
local _condition_1 = (entry.name)
|
|
3050
|
-
if _condition_1 == nil then
|
|
3051
|
-
_condition_1 = "SceneModel"
|
|
3052
|
-
end
|
|
3053
|
-
local name = _condition_1
|
|
3054
|
-
local palette = buildData.palette
|
|
3055
|
-
local parts = buildData.parts
|
|
3056
|
-
local model = Instance.new("Model")
|
|
3057
|
-
model.Name = name
|
|
3058
|
-
local _condition_2 = rotation[1]
|
|
3059
|
-
if _condition_2 == nil then
|
|
3060
|
-
_condition_2 = 0
|
|
3061
|
-
end
|
|
3062
|
-
local _exp = math.rad(_condition_2)
|
|
3063
|
-
local _condition_3 = rotation[2]
|
|
3064
|
-
if _condition_3 == nil then
|
|
3065
|
-
_condition_3 = 0
|
|
3066
|
-
end
|
|
3067
|
-
local _exp_1 = math.rad(_condition_3)
|
|
3068
|
-
local _condition_4 = rotation[3]
|
|
3069
|
-
if _condition_4 == nil then
|
|
3070
|
-
_condition_4 = 0
|
|
3071
|
-
end
|
|
3072
|
-
local rotCF = CFrame.Angles(_exp, _exp_1, math.rad(_condition_4))
|
|
3073
|
-
local _condition_5 = position[1]
|
|
3074
|
-
if _condition_5 == nil then
|
|
3075
|
-
_condition_5 = 0
|
|
3076
|
-
end
|
|
3077
|
-
local _condition_6 = position[2]
|
|
3078
|
-
if _condition_6 == nil then
|
|
3079
|
-
_condition_6 = 0
|
|
3080
|
-
end
|
|
3081
|
-
local _condition_7 = position[3]
|
|
3082
|
-
if _condition_7 == nil then
|
|
3083
|
-
_condition_7 = 0
|
|
3084
|
-
end
|
|
3085
|
-
local originCF = CFrame.new(_condition_5, _condition_6, _condition_7) * rotCF
|
|
3086
|
-
local partCount = 0
|
|
3087
|
-
for _1, partArr in parts do
|
|
3088
|
-
local localX = partArr[1]
|
|
3089
|
-
local localY = partArr[2]
|
|
3090
|
-
local localZ = partArr[3]
|
|
3091
|
-
local sizeX = partArr[4]
|
|
3092
|
-
local sizeY = partArr[5]
|
|
3093
|
-
local sizeZ = partArr[6]
|
|
3094
|
-
local rotX = partArr[7]
|
|
3095
|
-
local rotY = partArr[8]
|
|
3096
|
-
local rotZ = partArr[9]
|
|
3097
|
-
local paletteKey = partArr[10]
|
|
3098
|
-
local _condition_8 = (partArr[11])
|
|
3099
|
-
if _condition_8 == nil then
|
|
3100
|
-
_condition_8 = "Block"
|
|
3101
|
-
end
|
|
3102
|
-
local shape = _condition_8
|
|
3103
|
-
local _condition_9 = (partArr[12])
|
|
3104
|
-
if _condition_9 == nil then
|
|
3105
|
-
_condition_9 = 0
|
|
3106
|
-
end
|
|
3107
|
-
local transparency = _condition_9
|
|
3108
|
-
local _condition_10 = SHAPE_CLASSES[shape]
|
|
3109
|
-
if _condition_10 == nil then
|
|
3110
|
-
_condition_10 = "Part"
|
|
3111
|
-
end
|
|
3112
|
-
local className = _condition_10
|
|
3113
|
-
local part = Instance.new(className)
|
|
3114
|
-
if className == "Part" and shape ~= "Block" then
|
|
3115
|
-
if shape == "Cylinder" then
|
|
3116
|
-
part.Shape = Enum.PartType.Cylinder
|
|
3117
|
-
elseif shape == "Ball" then
|
|
3118
|
-
part.Shape = Enum.PartType.Ball
|
|
3119
|
-
end
|
|
3120
|
-
end
|
|
3121
|
-
part.Size = Vector3.new(sizeX, sizeY, sizeZ)
|
|
3122
|
-
-- Apply local rotation then world transform
|
|
3123
|
-
local localRotCF = CFrame.Angles(math.rad(rotX), math.rad(rotY), math.rad(rotZ))
|
|
3124
|
-
local localPosCF = CFrame.new(localX, localY, localZ) * localRotCF
|
|
3125
|
-
local worldCF = originCF * localPosCF
|
|
3126
|
-
part.CFrame = worldCF
|
|
3127
|
-
part.Anchored = true
|
|
3128
|
-
if transparency > 0 then
|
|
3129
|
-
part.Transparency = transparency
|
|
3130
|
-
end
|
|
3131
|
-
local paletteEntry = palette[paletteKey]
|
|
3132
|
-
if paletteEntry then
|
|
3133
|
-
local _binding_2 = paletteEntry
|
|
3134
|
-
local colorName = _binding_2[1]
|
|
3135
|
-
local materialName = _binding_2[2]
|
|
3136
|
-
local variantName = _binding_2[3]
|
|
3137
|
-
pcall(function()
|
|
3138
|
-
part.BrickColor = BrickColor.new(colorName)
|
|
3139
|
-
end)
|
|
3140
|
-
pcall(function()
|
|
3141
|
-
local mat = MATERIAL_BY_NAME[materialName]
|
|
3142
|
-
if mat ~= nil then
|
|
3143
|
-
part.Material = mat
|
|
3144
|
-
end
|
|
3145
|
-
end)
|
|
3146
|
-
if variantName ~= nil and variantName ~= "" then
|
|
3147
|
-
pcall(function()
|
|
3148
|
-
part.MaterialVariant = variantName
|
|
3149
|
-
end)
|
|
3150
|
-
end
|
|
3151
|
-
end
|
|
3152
|
-
part.Parent = model
|
|
3153
|
-
partCount += 1
|
|
3154
|
-
end
|
|
3155
|
-
model.Parent = parentInstance
|
|
3156
|
-
modelCount += 1
|
|
3157
|
-
totalParts += partCount
|
|
3158
|
-
local _arg0 = {
|
|
3159
|
-
name = name,
|
|
3160
|
-
partCount = partCount,
|
|
3161
|
-
modelPath = getInstancePath(model),
|
|
3162
|
-
}
|
|
3163
|
-
table.insert(models, _arg0)
|
|
3164
|
-
end
|
|
3165
|
-
return {
|
|
3166
|
-
success = true,
|
|
3167
|
-
modelCount = modelCount,
|
|
3168
|
-
totalParts = totalParts,
|
|
3169
|
-
models = models,
|
|
3170
|
-
}
|
|
3171
|
-
end)
|
|
3172
|
-
if success and result then
|
|
3173
|
-
finishRecording(recordingId, true)
|
|
3174
|
-
return result
|
|
3175
|
-
else
|
|
3176
|
-
finishRecording(recordingId, false)
|
|
3177
|
-
return {
|
|
3178
|
-
error = `Failed to import scene: {result}`,
|
|
3179
|
-
}
|
|
3180
|
-
end
|
|
3181
|
-
end
|
|
3182
|
-
local function searchMaterials(requestData)
|
|
3183
|
-
local _condition = (requestData.query)
|
|
3184
|
-
if _condition == nil then
|
|
3185
|
-
_condition = ""
|
|
3186
|
-
end
|
|
3187
|
-
local query = string.lower(_condition)
|
|
3188
|
-
local _condition_1 = (requestData.maxResults)
|
|
3189
|
-
if _condition_1 == nil then
|
|
3190
|
-
_condition_1 = 50
|
|
3191
|
-
end
|
|
3192
|
-
local maxResults = _condition_1
|
|
3193
|
-
local success, result = pcall(function()
|
|
3194
|
-
local children = MaterialService:GetChildren()
|
|
3195
|
-
local materials = {}
|
|
3196
|
-
for _, child in children do
|
|
3197
|
-
if not child:IsA("MaterialVariant") then
|
|
3198
|
-
continue
|
|
3199
|
-
end
|
|
3200
|
-
local nameMatch = query == "" or (string.find(string.lower(child.Name), query)) ~= nil
|
|
3201
|
-
if not nameMatch then
|
|
3202
|
-
continue
|
|
3203
|
-
end
|
|
3204
|
-
local _arg0 = {
|
|
3205
|
-
name = child.Name,
|
|
3206
|
-
baseMaterial = child.BaseMaterial.Name,
|
|
3207
|
-
}
|
|
3208
|
-
table.insert(materials, _arg0)
|
|
3209
|
-
if #materials >= maxResults then
|
|
3210
|
-
break
|
|
3211
|
-
end
|
|
3212
|
-
end
|
|
3213
|
-
return {
|
|
3214
|
-
success = true,
|
|
3215
|
-
materials = materials,
|
|
3216
|
-
total = #materials,
|
|
3217
|
-
}
|
|
3218
|
-
end)
|
|
3219
|
-
if success and result then
|
|
3220
|
-
return result
|
|
3221
|
-
else
|
|
3222
|
-
return {
|
|
3223
|
-
error = `Failed to search materials: {result}`,
|
|
3224
|
-
}
|
|
3225
|
-
end
|
|
3226
|
-
end
|
|
3227
|
-
return {
|
|
3228
|
-
exportBuild = exportBuild,
|
|
3229
|
-
importBuild = importBuild,
|
|
3230
|
-
importScene = importScene,
|
|
3231
|
-
searchMaterials = searchMaterials,
|
|
3232
|
-
}
|
|
3233
|
-
]]></string>
|
|
3234
|
-
</Properties>
|
|
3235
|
-
</Item>
|
|
3236
|
-
<Item class="ModuleScript" referent="10">
|
|
3237
2643
|
<Properties>
|
|
3238
2644
|
<string name="Name">CaptureHandlers</string>
|
|
3239
2645
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -3448,7 +2854,7 @@ return {
|
|
|
3448
2854
|
]]></string>
|
|
3449
2855
|
</Properties>
|
|
3450
2856
|
</Item>
|
|
3451
|
-
<Item class="ModuleScript" referent="
|
|
2857
|
+
<Item class="ModuleScript" referent="10">
|
|
3452
2858
|
<Properties>
|
|
3453
2859
|
<string name="Name">EvalRuntimeHandlers</string>
|
|
3454
2860
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -3602,7 +3008,7 @@ return {
|
|
|
3602
3008
|
]]></string>
|
|
3603
3009
|
</Properties>
|
|
3604
3010
|
</Item>
|
|
3605
|
-
<Item class="ModuleScript" referent="
|
|
3011
|
+
<Item class="ModuleScript" referent="11">
|
|
3606
3012
|
<Properties>
|
|
3607
3013
|
<string name="Name">GenerateModelHandlers</string>
|
|
3608
3014
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -3807,7 +3213,7 @@ return {
|
|
|
3807
3213
|
]]></string>
|
|
3808
3214
|
</Properties>
|
|
3809
3215
|
</Item>
|
|
3810
|
-
<Item class="ModuleScript" referent="
|
|
3216
|
+
<Item class="ModuleScript" referent="12">
|
|
3811
3217
|
<Properties>
|
|
3812
3218
|
<string name="Name">InputHandlers</string>
|
|
3813
3219
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -4007,514 +3413,7 @@ return {
|
|
|
4007
3413
|
]]></string>
|
|
4008
3414
|
</Properties>
|
|
4009
3415
|
</Item>
|
|
4010
|
-
<Item class="ModuleScript" referent="
|
|
4011
|
-
<Properties>
|
|
4012
|
-
<string name="Name">InstanceHandlers</string>
|
|
4013
|
-
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
4014
|
-
local TS = require(script.Parent.Parent.Parent.include.RuntimeLib)
|
|
4015
|
-
local Utils = TS.import(script, script.Parent.Parent, "Utils")
|
|
4016
|
-
local Recording = TS.import(script, script.Parent.Parent, "Recording")
|
|
4017
|
-
local _binding = Utils
|
|
4018
|
-
local getInstancePath = _binding.getInstancePath
|
|
4019
|
-
local getInstanceByPath = _binding.getInstanceByPath
|
|
4020
|
-
local convertPropertyValue = _binding.convertPropertyValue
|
|
4021
|
-
local _binding_1 = Recording
|
|
4022
|
-
local beginRecording = _binding_1.beginRecording
|
|
4023
|
-
local finishRecording = _binding_1.finishRecording
|
|
4024
|
-
local function processObjectEntries(objects, createFn)
|
|
4025
|
-
local results = {}
|
|
4026
|
-
local successCount = 0
|
|
4027
|
-
local failureCount = 0
|
|
4028
|
-
local loopSuccess, loopError = pcall(function()
|
|
4029
|
-
for _, entry in objects do
|
|
4030
|
-
if not (type(entry) == "table") then
|
|
4031
|
-
failureCount += 1
|
|
4032
|
-
table.insert(results, {
|
|
4033
|
-
success = false,
|
|
4034
|
-
error = "Each object entry must be a table",
|
|
4035
|
-
})
|
|
4036
|
-
continue
|
|
4037
|
-
end
|
|
4038
|
-
local objData = entry
|
|
4039
|
-
local className = objData.className
|
|
4040
|
-
local parentPath = objData.parent
|
|
4041
|
-
if not (className ~= "" and className) or not (parentPath ~= "" and parentPath) then
|
|
4042
|
-
failureCount += 1
|
|
4043
|
-
table.insert(results, {
|
|
4044
|
-
success = false,
|
|
4045
|
-
error = "Class name and parent are required",
|
|
4046
|
-
})
|
|
4047
|
-
continue
|
|
4048
|
-
end
|
|
4049
|
-
local entrySuccess, entryResult = pcall(function()
|
|
4050
|
-
return createFn(objData)
|
|
4051
|
-
end)
|
|
4052
|
-
if not entrySuccess then
|
|
4053
|
-
failureCount += 1
|
|
4054
|
-
local _arg0 = {
|
|
4055
|
-
success = false,
|
|
4056
|
-
className = className,
|
|
4057
|
-
parent = parentPath,
|
|
4058
|
-
error = tostring(entryResult),
|
|
4059
|
-
}
|
|
4060
|
-
table.insert(results, _arg0)
|
|
4061
|
-
continue
|
|
4062
|
-
end
|
|
4063
|
-
if entryResult.instance ~= nil then
|
|
4064
|
-
successCount += 1
|
|
4065
|
-
local _arg0 = {
|
|
4066
|
-
success = true,
|
|
4067
|
-
className = entryResult.className,
|
|
4068
|
-
parent = entryResult.parentPath,
|
|
4069
|
-
instancePath = getInstancePath(entryResult.instance),
|
|
4070
|
-
name = entryResult.instance.Name,
|
|
4071
|
-
}
|
|
4072
|
-
table.insert(results, _arg0)
|
|
4073
|
-
else
|
|
4074
|
-
failureCount += 1
|
|
4075
|
-
local _object = {
|
|
4076
|
-
success = false,
|
|
4077
|
-
}
|
|
4078
|
-
local _left = "className"
|
|
4079
|
-
local _condition = entryResult.className
|
|
4080
|
-
if _condition == nil then
|
|
4081
|
-
_condition = className
|
|
4082
|
-
end
|
|
4083
|
-
_object[_left] = _condition
|
|
4084
|
-
local _left_1 = "parent"
|
|
4085
|
-
local _condition_1 = entryResult.parentPath
|
|
4086
|
-
if _condition_1 == nil then
|
|
4087
|
-
_condition_1 = parentPath
|
|
4088
|
-
end
|
|
4089
|
-
_object[_left_1] = _condition_1
|
|
4090
|
-
_object.error = entryResult.error
|
|
4091
|
-
table.insert(results, _object)
|
|
4092
|
-
end
|
|
4093
|
-
end
|
|
4094
|
-
end)
|
|
4095
|
-
if not loopSuccess then
|
|
4096
|
-
failureCount += 1
|
|
4097
|
-
local _arg0 = {
|
|
4098
|
-
success = false,
|
|
4099
|
-
error = `Unexpected mass create failure: {tostring(loopError)}`,
|
|
4100
|
-
}
|
|
4101
|
-
table.insert(results, _arg0)
|
|
4102
|
-
end
|
|
4103
|
-
return {
|
|
4104
|
-
results = results,
|
|
4105
|
-
successCount = successCount,
|
|
4106
|
-
failureCount = failureCount,
|
|
4107
|
-
}
|
|
4108
|
-
end
|
|
4109
|
-
local function createObject(requestData)
|
|
4110
|
-
local className = requestData.className
|
|
4111
|
-
local parentPath = requestData.parent
|
|
4112
|
-
local name = requestData.name
|
|
4113
|
-
local properties = (requestData.properties) or {}
|
|
4114
|
-
if not (className ~= "" and className) or not (parentPath ~= "" and parentPath) then
|
|
4115
|
-
return {
|
|
4116
|
-
error = "Class name and parent are required",
|
|
4117
|
-
}
|
|
4118
|
-
end
|
|
4119
|
-
local parentInstance = getInstanceByPath(parentPath)
|
|
4120
|
-
if not parentInstance then
|
|
4121
|
-
return {
|
|
4122
|
-
error = `Parent instance not found: {parentPath}`,
|
|
4123
|
-
}
|
|
4124
|
-
end
|
|
4125
|
-
local recordingId = beginRecording(`Create {className}`)
|
|
4126
|
-
local success, newInstance = pcall(function()
|
|
4127
|
-
local instance = Instance.new(className)
|
|
4128
|
-
if name ~= "" and name then
|
|
4129
|
-
instance.Name = name
|
|
4130
|
-
end
|
|
4131
|
-
for propertyName, propertyValue in pairs(properties) do
|
|
4132
|
-
pcall(function()
|
|
4133
|
-
local converted = convertPropertyValue(instance, propertyName, propertyValue)
|
|
4134
|
-
instance[propertyName] = if converted ~= nil then converted else propertyValue
|
|
4135
|
-
end)
|
|
4136
|
-
end
|
|
4137
|
-
instance.Parent = parentInstance
|
|
4138
|
-
return instance
|
|
4139
|
-
end)
|
|
4140
|
-
if success and newInstance then
|
|
4141
|
-
finishRecording(recordingId, true)
|
|
4142
|
-
return {
|
|
4143
|
-
success = true,
|
|
4144
|
-
className = className,
|
|
4145
|
-
parent = parentPath,
|
|
4146
|
-
instancePath = getInstancePath(newInstance),
|
|
4147
|
-
name = newInstance.Name,
|
|
4148
|
-
message = "Object created successfully",
|
|
4149
|
-
}
|
|
4150
|
-
else
|
|
4151
|
-
finishRecording(recordingId, false)
|
|
4152
|
-
return {
|
|
4153
|
-
error = `Failed to create object: {newInstance}`,
|
|
4154
|
-
className = className,
|
|
4155
|
-
parent = parentPath,
|
|
4156
|
-
}
|
|
4157
|
-
end
|
|
4158
|
-
end
|
|
4159
|
-
local function deleteObject(requestData)
|
|
4160
|
-
local instancePath = requestData.instancePath
|
|
4161
|
-
if not (instancePath ~= "" and instancePath) then
|
|
4162
|
-
return {
|
|
4163
|
-
error = "Instance path is required",
|
|
4164
|
-
}
|
|
4165
|
-
end
|
|
4166
|
-
local instance = getInstanceByPath(instancePath)
|
|
4167
|
-
if not instance then
|
|
4168
|
-
return {
|
|
4169
|
-
error = `Instance not found: {instancePath}`,
|
|
4170
|
-
}
|
|
4171
|
-
end
|
|
4172
|
-
if instance == game then
|
|
4173
|
-
return {
|
|
4174
|
-
error = "Cannot delete the game instance",
|
|
4175
|
-
}
|
|
4176
|
-
end
|
|
4177
|
-
local recordingId = beginRecording(`Delete {instance.ClassName} ({instance.Name})`)
|
|
4178
|
-
local success, result = pcall(function()
|
|
4179
|
-
instance:Destroy()
|
|
4180
|
-
return true
|
|
4181
|
-
end)
|
|
4182
|
-
if success then
|
|
4183
|
-
finishRecording(recordingId, true)
|
|
4184
|
-
return {
|
|
4185
|
-
success = true,
|
|
4186
|
-
instancePath = instancePath,
|
|
4187
|
-
message = "Object deleted successfully",
|
|
4188
|
-
}
|
|
4189
|
-
else
|
|
4190
|
-
finishRecording(recordingId, false)
|
|
4191
|
-
return {
|
|
4192
|
-
error = `Failed to delete object: {result}`,
|
|
4193
|
-
instancePath = instancePath,
|
|
4194
|
-
}
|
|
4195
|
-
end
|
|
4196
|
-
end
|
|
4197
|
-
local function massCreateObjects(requestData)
|
|
4198
|
-
local objects = requestData.objects
|
|
4199
|
-
if not objects or not (type(objects) == "table") or #objects == 0 then
|
|
4200
|
-
return {
|
|
4201
|
-
error = "Objects array is required",
|
|
4202
|
-
}
|
|
4203
|
-
end
|
|
4204
|
-
local recordingId = beginRecording("Mass create objects")
|
|
4205
|
-
local _binding_2 = processObjectEntries(objects, function(objData)
|
|
4206
|
-
local className = objData.className
|
|
4207
|
-
local parentPath = objData.parent
|
|
4208
|
-
local name = objData.name
|
|
4209
|
-
local properties = (objData.properties) or {}
|
|
4210
|
-
local parentInstance = getInstanceByPath(parentPath)
|
|
4211
|
-
if not parentInstance then
|
|
4212
|
-
return {
|
|
4213
|
-
error = "Parent instance not found",
|
|
4214
|
-
className = className,
|
|
4215
|
-
parentPath = parentPath,
|
|
4216
|
-
}
|
|
4217
|
-
end
|
|
4218
|
-
local success, newInstance = pcall(function()
|
|
4219
|
-
local instance = Instance.new(className)
|
|
4220
|
-
if name ~= "" and name then
|
|
4221
|
-
instance.Name = name
|
|
4222
|
-
end
|
|
4223
|
-
for propertyName, propertyValue in pairs(properties) do
|
|
4224
|
-
pcall(function()
|
|
4225
|
-
local converted = convertPropertyValue(instance, propertyName, propertyValue)
|
|
4226
|
-
instance[propertyName] = if converted ~= nil then converted else propertyValue
|
|
4227
|
-
end)
|
|
4228
|
-
end
|
|
4229
|
-
instance.Parent = parentInstance
|
|
4230
|
-
return instance
|
|
4231
|
-
end)
|
|
4232
|
-
if not success or not newInstance then
|
|
4233
|
-
return {
|
|
4234
|
-
error = tostring(newInstance),
|
|
4235
|
-
className = className,
|
|
4236
|
-
parentPath = parentPath,
|
|
4237
|
-
}
|
|
4238
|
-
end
|
|
4239
|
-
return {
|
|
4240
|
-
instance = newInstance,
|
|
4241
|
-
className = className,
|
|
4242
|
-
parentPath = parentPath,
|
|
4243
|
-
}
|
|
4244
|
-
end)
|
|
4245
|
-
local results = _binding_2.results
|
|
4246
|
-
local successCount = _binding_2.successCount
|
|
4247
|
-
local failureCount = _binding_2.failureCount
|
|
4248
|
-
finishRecording(recordingId, successCount > 0)
|
|
4249
|
-
return {
|
|
4250
|
-
results = results,
|
|
4251
|
-
summary = {
|
|
4252
|
-
total = #objects,
|
|
4253
|
-
succeeded = successCount,
|
|
4254
|
-
failed = failureCount,
|
|
4255
|
-
},
|
|
4256
|
-
}
|
|
4257
|
-
end
|
|
4258
|
-
local function performSmartDuplicate(requestData, useRecording)
|
|
4259
|
-
if useRecording == nil then
|
|
4260
|
-
useRecording = true
|
|
4261
|
-
end
|
|
4262
|
-
local instancePath = requestData.instancePath
|
|
4263
|
-
local count = requestData.count
|
|
4264
|
-
local options = (requestData.options) or {}
|
|
4265
|
-
if not (instancePath ~= "" and instancePath) or not (count ~= 0 and count == count and count) or count < 1 then
|
|
4266
|
-
return {
|
|
4267
|
-
error = "Instance path and count > 0 are required",
|
|
4268
|
-
}
|
|
4269
|
-
end
|
|
4270
|
-
local instance = getInstanceByPath(instancePath)
|
|
4271
|
-
if not instance then
|
|
4272
|
-
return {
|
|
4273
|
-
error = `Instance not found: {instancePath}`,
|
|
4274
|
-
}
|
|
4275
|
-
end
|
|
4276
|
-
local recordingId = if useRecording then beginRecording(`Smart duplicate {instance.Name}`) else nil
|
|
4277
|
-
local results = {}
|
|
4278
|
-
local successCount = 0
|
|
4279
|
-
local failureCount = 0
|
|
4280
|
-
do
|
|
4281
|
-
local _i = 1
|
|
4282
|
-
local _shouldIncrement = false
|
|
4283
|
-
while true do
|
|
4284
|
-
local i = _i
|
|
4285
|
-
if _shouldIncrement then
|
|
4286
|
-
i += 1
|
|
4287
|
-
else
|
|
4288
|
-
_shouldIncrement = true
|
|
4289
|
-
end
|
|
4290
|
-
if not (i <= count) then
|
|
4291
|
-
break
|
|
4292
|
-
end
|
|
4293
|
-
local success, newInstance = pcall(function()
|
|
4294
|
-
local clone = instance:Clone()
|
|
4295
|
-
local _value = options.namePattern
|
|
4296
|
-
if _value ~= 0 and _value == _value and _value ~= "" and _value then
|
|
4297
|
-
local _exp = (options.namePattern)
|
|
4298
|
-
local _arg1 = tostring(i)
|
|
4299
|
-
clone.Name = (string.gsub(_exp, "{n}", _arg1))
|
|
4300
|
-
else
|
|
4301
|
-
clone.Name = instance.Name .. tostring(i)
|
|
4302
|
-
end
|
|
4303
|
-
local _condition = options.positionOffset
|
|
4304
|
-
if _condition ~= 0 and _condition == _condition and _condition ~= "" and _condition then
|
|
4305
|
-
_condition = clone:IsA("BasePart")
|
|
4306
|
-
end
|
|
4307
|
-
if _condition ~= 0 and _condition == _condition and _condition ~= "" and _condition then
|
|
4308
|
-
local offset = options.positionOffset
|
|
4309
|
-
local currentPos = clone.Position
|
|
4310
|
-
local _exp = currentPos.X
|
|
4311
|
-
local _condition_1 = offset[1]
|
|
4312
|
-
if _condition_1 == nil then
|
|
4313
|
-
_condition_1 = 0
|
|
4314
|
-
end
|
|
4315
|
-
local _exp_1 = _exp + _condition_1 * i
|
|
4316
|
-
local _exp_2 = currentPos.Y
|
|
4317
|
-
local _condition_2 = offset[2]
|
|
4318
|
-
if _condition_2 == nil then
|
|
4319
|
-
_condition_2 = 0
|
|
4320
|
-
end
|
|
4321
|
-
local _exp_3 = _exp_2 + _condition_2 * i
|
|
4322
|
-
local _exp_4 = currentPos.Z
|
|
4323
|
-
local _condition_3 = offset[3]
|
|
4324
|
-
if _condition_3 == nil then
|
|
4325
|
-
_condition_3 = 0
|
|
4326
|
-
end
|
|
4327
|
-
clone.Position = Vector3.new(_exp_1, _exp_3, _exp_4 + _condition_3 * i)
|
|
4328
|
-
end
|
|
4329
|
-
local _condition_1 = options.rotationOffset
|
|
4330
|
-
if _condition_1 ~= 0 and _condition_1 == _condition_1 and _condition_1 ~= "" and _condition_1 then
|
|
4331
|
-
_condition_1 = clone:IsA("BasePart")
|
|
4332
|
-
end
|
|
4333
|
-
if _condition_1 ~= 0 and _condition_1 == _condition_1 and _condition_1 ~= "" and _condition_1 then
|
|
4334
|
-
local offset = options.rotationOffset
|
|
4335
|
-
local _cFrame = clone.CFrame
|
|
4336
|
-
local _condition_2 = offset[1]
|
|
4337
|
-
if _condition_2 == nil then
|
|
4338
|
-
_condition_2 = 0
|
|
4339
|
-
end
|
|
4340
|
-
local _exp = math.rad(_condition_2 * i)
|
|
4341
|
-
local _condition_3 = offset[2]
|
|
4342
|
-
if _condition_3 == nil then
|
|
4343
|
-
_condition_3 = 0
|
|
4344
|
-
end
|
|
4345
|
-
local _exp_1 = math.rad(_condition_3 * i)
|
|
4346
|
-
local _condition_4 = offset[3]
|
|
4347
|
-
if _condition_4 == nil then
|
|
4348
|
-
_condition_4 = 0
|
|
4349
|
-
end
|
|
4350
|
-
local _arg0 = CFrame.Angles(_exp, _exp_1, math.rad(_condition_4 * i))
|
|
4351
|
-
clone.CFrame = _cFrame * _arg0
|
|
4352
|
-
end
|
|
4353
|
-
local _condition_2 = options.scaleOffset
|
|
4354
|
-
if _condition_2 ~= 0 and _condition_2 == _condition_2 and _condition_2 ~= "" and _condition_2 then
|
|
4355
|
-
_condition_2 = clone:IsA("BasePart")
|
|
4356
|
-
end
|
|
4357
|
-
if _condition_2 ~= 0 and _condition_2 == _condition_2 and _condition_2 ~= "" and _condition_2 then
|
|
4358
|
-
local offset = options.scaleOffset
|
|
4359
|
-
local currentSize = clone.Size
|
|
4360
|
-
local _exp = currentSize.X
|
|
4361
|
-
local _condition_3 = offset[1]
|
|
4362
|
-
if _condition_3 == nil then
|
|
4363
|
-
_condition_3 = 1
|
|
4364
|
-
end
|
|
4365
|
-
local _exp_1 = _exp * (_condition_3 ^ i)
|
|
4366
|
-
local _exp_2 = currentSize.Y
|
|
4367
|
-
local _condition_4 = offset[2]
|
|
4368
|
-
if _condition_4 == nil then
|
|
4369
|
-
_condition_4 = 1
|
|
4370
|
-
end
|
|
4371
|
-
local _exp_3 = _exp_2 * (_condition_4 ^ i)
|
|
4372
|
-
local _exp_4 = currentSize.Z
|
|
4373
|
-
local _condition_5 = offset[3]
|
|
4374
|
-
if _condition_5 == nil then
|
|
4375
|
-
_condition_5 = 1
|
|
4376
|
-
end
|
|
4377
|
-
clone.Size = Vector3.new(_exp_1, _exp_3, _exp_4 * (_condition_5 ^ i))
|
|
4378
|
-
end
|
|
4379
|
-
local _value_1 = options.propertyVariations
|
|
4380
|
-
if _value_1 ~= 0 and _value_1 == _value_1 and _value_1 ~= "" and _value_1 then
|
|
4381
|
-
for propName, values in pairs(options.propertyVariations) do
|
|
4382
|
-
if values and #values > 0 then
|
|
4383
|
-
local valueIndex = ((i - 1) % #values)
|
|
4384
|
-
pcall(function()
|
|
4385
|
-
clone[propName] = values[valueIndex + 1]
|
|
4386
|
-
end)
|
|
4387
|
-
end
|
|
4388
|
-
end
|
|
4389
|
-
end
|
|
4390
|
-
local targetParents = options.targetParents
|
|
4391
|
-
local _value_2 = targetParents and targetParents[i]
|
|
4392
|
-
if _value_2 ~= "" and _value_2 then
|
|
4393
|
-
local targetParent = getInstanceByPath(targetParents[i])
|
|
4394
|
-
clone.Parent = targetParent or instance.Parent
|
|
4395
|
-
else
|
|
4396
|
-
clone.Parent = instance.Parent
|
|
4397
|
-
end
|
|
4398
|
-
return clone
|
|
4399
|
-
end)
|
|
4400
|
-
if success and newInstance then
|
|
4401
|
-
successCount += 1
|
|
4402
|
-
local _arg0 = {
|
|
4403
|
-
success = true,
|
|
4404
|
-
instancePath = getInstancePath(newInstance),
|
|
4405
|
-
name = newInstance.Name,
|
|
4406
|
-
index = i,
|
|
4407
|
-
}
|
|
4408
|
-
table.insert(results, _arg0)
|
|
4409
|
-
else
|
|
4410
|
-
failureCount += 1
|
|
4411
|
-
local _arg0 = {
|
|
4412
|
-
success = false,
|
|
4413
|
-
index = i,
|
|
4414
|
-
error = tostring(newInstance),
|
|
4415
|
-
}
|
|
4416
|
-
table.insert(results, _arg0)
|
|
4417
|
-
end
|
|
4418
|
-
_i = i
|
|
4419
|
-
end
|
|
4420
|
-
end
|
|
4421
|
-
finishRecording(recordingId, successCount > 0)
|
|
4422
|
-
return {
|
|
4423
|
-
results = results,
|
|
4424
|
-
summary = {
|
|
4425
|
-
total = count,
|
|
4426
|
-
succeeded = successCount,
|
|
4427
|
-
failed = failureCount,
|
|
4428
|
-
},
|
|
4429
|
-
sourceInstance = instancePath,
|
|
4430
|
-
}
|
|
4431
|
-
end
|
|
4432
|
-
local function smartDuplicate(requestData)
|
|
4433
|
-
return performSmartDuplicate(requestData, true)
|
|
4434
|
-
end
|
|
4435
|
-
local function massDuplicate(requestData)
|
|
4436
|
-
local duplications = requestData.duplications
|
|
4437
|
-
if not duplications or not (type(duplications) == "table") or #duplications == 0 then
|
|
4438
|
-
return {
|
|
4439
|
-
error = "Duplications array is required",
|
|
4440
|
-
}
|
|
4441
|
-
end
|
|
4442
|
-
local allResults = {}
|
|
4443
|
-
local totalSuccess = 0
|
|
4444
|
-
local totalFailures = 0
|
|
4445
|
-
local recordingId = beginRecording("Mass duplicate operations")
|
|
4446
|
-
for _, duplication in duplications do
|
|
4447
|
-
local result = performSmartDuplicate(duplication, false)
|
|
4448
|
-
table.insert(allResults, result)
|
|
4449
|
-
if result.summary then
|
|
4450
|
-
totalSuccess += result.summary.succeeded
|
|
4451
|
-
totalFailures += result.summary.failed
|
|
4452
|
-
end
|
|
4453
|
-
end
|
|
4454
|
-
finishRecording(recordingId, totalSuccess > 0)
|
|
4455
|
-
return {
|
|
4456
|
-
results = allResults,
|
|
4457
|
-
summary = {
|
|
4458
|
-
total = totalSuccess + totalFailures,
|
|
4459
|
-
succeeded = totalSuccess,
|
|
4460
|
-
failed = totalFailures,
|
|
4461
|
-
},
|
|
4462
|
-
}
|
|
4463
|
-
end
|
|
4464
|
-
local function cloneObject(requestData)
|
|
4465
|
-
local instancePath = requestData.instancePath
|
|
4466
|
-
local targetParentPath = requestData.targetParentPath
|
|
4467
|
-
if not (instancePath ~= "" and instancePath) or not (targetParentPath ~= "" and targetParentPath) then
|
|
4468
|
-
return {
|
|
4469
|
-
error = "Instance path and target parent path are required",
|
|
4470
|
-
}
|
|
4471
|
-
end
|
|
4472
|
-
local instance = getInstanceByPath(instancePath)
|
|
4473
|
-
if not instance then
|
|
4474
|
-
return {
|
|
4475
|
-
error = `Instance not found: {instancePath}`,
|
|
4476
|
-
}
|
|
4477
|
-
end
|
|
4478
|
-
local targetParent = getInstanceByPath(targetParentPath)
|
|
4479
|
-
if not targetParent then
|
|
4480
|
-
return {
|
|
4481
|
-
error = `Target parent not found: {targetParentPath}`,
|
|
4482
|
-
}
|
|
4483
|
-
end
|
|
4484
|
-
local recordingId = beginRecording(`Clone {instance.Name}`)
|
|
4485
|
-
local success, clone = pcall(function()
|
|
4486
|
-
local cloned = instance:Clone()
|
|
4487
|
-
cloned.Parent = targetParent
|
|
4488
|
-
return cloned
|
|
4489
|
-
end)
|
|
4490
|
-
if success and clone then
|
|
4491
|
-
finishRecording(recordingId, true)
|
|
4492
|
-
return {
|
|
4493
|
-
success = true,
|
|
4494
|
-
instancePath = getInstancePath(clone),
|
|
4495
|
-
name = clone.Name,
|
|
4496
|
-
className = clone.ClassName,
|
|
4497
|
-
parent = targetParentPath,
|
|
4498
|
-
message = "Object cloned successfully",
|
|
4499
|
-
}
|
|
4500
|
-
end
|
|
4501
|
-
finishRecording(recordingId, false)
|
|
4502
|
-
return {
|
|
4503
|
-
error = `Failed to clone object: {clone}`,
|
|
4504
|
-
}
|
|
4505
|
-
end
|
|
4506
|
-
return {
|
|
4507
|
-
createObject = createObject,
|
|
4508
|
-
deleteObject = deleteObject,
|
|
4509
|
-
massCreateObjects = massCreateObjects,
|
|
4510
|
-
smartDuplicate = smartDuplicate,
|
|
4511
|
-
massDuplicate = massDuplicate,
|
|
4512
|
-
cloneObject = cloneObject,
|
|
4513
|
-
}
|
|
4514
|
-
]]></string>
|
|
4515
|
-
</Properties>
|
|
4516
|
-
</Item>
|
|
4517
|
-
<Item class="ModuleScript" referent="15">
|
|
3416
|
+
<Item class="ModuleScript" referent="13">
|
|
4518
3417
|
<Properties>
|
|
4519
3418
|
<string name="Name">LogHandlers</string>
|
|
4520
3419
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -4540,7 +3439,7 @@ return {
|
|
|
4540
3439
|
]]></string>
|
|
4541
3440
|
</Properties>
|
|
4542
3441
|
</Item>
|
|
4543
|
-
<Item class="ModuleScript" referent="
|
|
3442
|
+
<Item class="ModuleScript" referent="14">
|
|
4544
3443
|
<Properties>
|
|
4545
3444
|
<string name="Name">MemoryHandlers</string>
|
|
4546
3445
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -4608,23 +3507,17 @@ return {
|
|
|
4608
3507
|
]]></string>
|
|
4609
3508
|
</Properties>
|
|
4610
3509
|
</Item>
|
|
4611
|
-
<Item class="ModuleScript" referent="
|
|
3510
|
+
<Item class="ModuleScript" referent="15">
|
|
4612
3511
|
<Properties>
|
|
4613
3512
|
<string name="Name">MetadataHandlers</string>
|
|
4614
3513
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
4615
3514
|
local TS = require(script.Parent.Parent.Parent.include.RuntimeLib)
|
|
4616
|
-
local CollectionService = TS.import(script, script.Parent.Parent.Parent, "node_modules", "@rbxts", "services").CollectionService
|
|
4617
3515
|
local Utils = TS.import(script, script.Parent.Parent, "Utils")
|
|
4618
|
-
local Recording = TS.import(script, script.Parent.Parent, "Recording")
|
|
4619
3516
|
local LuauExec = TS.import(script, script.Parent.Parent, "LuauExec")
|
|
4620
|
-
local ChangeHistoryService = game:GetService("ChangeHistoryService")
|
|
4621
3517
|
local Selection = game:GetService("Selection")
|
|
4622
3518
|
local _binding = Utils
|
|
4623
3519
|
local getInstancePath = _binding.getInstancePath
|
|
4624
3520
|
local getInstanceByPath = _binding.getInstanceByPath
|
|
4625
|
-
local _binding_1 = Recording
|
|
4626
|
-
local beginRecording = _binding_1.beginRecording
|
|
4627
|
-
local finishRecording = _binding_1.finishRecording
|
|
4628
3521
|
local function serializeValue(value)
|
|
4629
3522
|
local _value = value
|
|
4630
3523
|
local vType = typeof(_value)
|
|
@@ -4676,127 +3569,6 @@ local function serializeValue(value)
|
|
|
4676
3569
|
end
|
|
4677
3570
|
return value
|
|
4678
3571
|
end
|
|
4679
|
-
local function deserializeValue(attributeValue, valueType)
|
|
4680
|
-
local _attributeValue = attributeValue
|
|
4681
|
-
if not (type(_attributeValue) == "table") then
|
|
4682
|
-
return attributeValue
|
|
4683
|
-
end
|
|
4684
|
-
local tbl = attributeValue
|
|
4685
|
-
local _condition = (tbl._type)
|
|
4686
|
-
if _condition == nil then
|
|
4687
|
-
_condition = valueType
|
|
4688
|
-
end
|
|
4689
|
-
local t = _condition
|
|
4690
|
-
if t == "Vector3" then
|
|
4691
|
-
local _condition_1 = (tbl.X)
|
|
4692
|
-
if _condition_1 == nil then
|
|
4693
|
-
_condition_1 = 0
|
|
4694
|
-
end
|
|
4695
|
-
local _condition_2 = (tbl.Y)
|
|
4696
|
-
if _condition_2 == nil then
|
|
4697
|
-
_condition_2 = 0
|
|
4698
|
-
end
|
|
4699
|
-
local _condition_3 = (tbl.Z)
|
|
4700
|
-
if _condition_3 == nil then
|
|
4701
|
-
_condition_3 = 0
|
|
4702
|
-
end
|
|
4703
|
-
return Vector3.new(_condition_1, _condition_2, _condition_3)
|
|
4704
|
-
elseif t == "Color3" then
|
|
4705
|
-
local _condition_1 = (tbl.R)
|
|
4706
|
-
if _condition_1 == nil then
|
|
4707
|
-
_condition_1 = 0
|
|
4708
|
-
end
|
|
4709
|
-
local _condition_2 = (tbl.G)
|
|
4710
|
-
if _condition_2 == nil then
|
|
4711
|
-
_condition_2 = 0
|
|
4712
|
-
end
|
|
4713
|
-
local _condition_3 = (tbl.B)
|
|
4714
|
-
if _condition_3 == nil then
|
|
4715
|
-
_condition_3 = 0
|
|
4716
|
-
end
|
|
4717
|
-
return Color3.new(_condition_1, _condition_2, _condition_3)
|
|
4718
|
-
elseif t == "UDim2" then
|
|
4719
|
-
local x = tbl.X
|
|
4720
|
-
local y = tbl.Y
|
|
4721
|
-
local _result = x
|
|
4722
|
-
if _result ~= nil then
|
|
4723
|
-
_result = _result.Scale
|
|
4724
|
-
end
|
|
4725
|
-
local _condition_1 = _result
|
|
4726
|
-
if _condition_1 == nil then
|
|
4727
|
-
_condition_1 = 0
|
|
4728
|
-
end
|
|
4729
|
-
local _result_1 = x
|
|
4730
|
-
if _result_1 ~= nil then
|
|
4731
|
-
_result_1 = _result_1.Offset
|
|
4732
|
-
end
|
|
4733
|
-
local _condition_2 = _result_1
|
|
4734
|
-
if _condition_2 == nil then
|
|
4735
|
-
_condition_2 = 0
|
|
4736
|
-
end
|
|
4737
|
-
local _result_2 = y
|
|
4738
|
-
if _result_2 ~= nil then
|
|
4739
|
-
_result_2 = _result_2.Scale
|
|
4740
|
-
end
|
|
4741
|
-
local _condition_3 = _result_2
|
|
4742
|
-
if _condition_3 == nil then
|
|
4743
|
-
_condition_3 = 0
|
|
4744
|
-
end
|
|
4745
|
-
local _result_3 = y
|
|
4746
|
-
if _result_3 ~= nil then
|
|
4747
|
-
_result_3 = _result_3.Offset
|
|
4748
|
-
end
|
|
4749
|
-
local _condition_4 = _result_3
|
|
4750
|
-
if _condition_4 == nil then
|
|
4751
|
-
_condition_4 = 0
|
|
4752
|
-
end
|
|
4753
|
-
return UDim2.new(_condition_1, _condition_2, _condition_3, _condition_4)
|
|
4754
|
-
elseif t == "BrickColor" then
|
|
4755
|
-
local _condition_1 = (tbl.Name)
|
|
4756
|
-
if _condition_1 == nil then
|
|
4757
|
-
_condition_1 = "Medium stone grey"
|
|
4758
|
-
end
|
|
4759
|
-
return BrickColor.new(_condition_1)
|
|
4760
|
-
end
|
|
4761
|
-
return attributeValue
|
|
4762
|
-
end
|
|
4763
|
-
local function setAttribute(requestData)
|
|
4764
|
-
local instancePath = requestData.instancePath
|
|
4765
|
-
local attributeName = requestData.attributeName
|
|
4766
|
-
local attributeValue = requestData.attributeValue
|
|
4767
|
-
local valueType = requestData.valueType
|
|
4768
|
-
if not (instancePath ~= "" and instancePath) or not (attributeName ~= "" and attributeName) then
|
|
4769
|
-
return {
|
|
4770
|
-
error = "Instance path and attribute name are required",
|
|
4771
|
-
}
|
|
4772
|
-
end
|
|
4773
|
-
local instance = getInstanceByPath(instancePath)
|
|
4774
|
-
if not instance then
|
|
4775
|
-
return {
|
|
4776
|
-
error = `Instance not found: {instancePath}`,
|
|
4777
|
-
}
|
|
4778
|
-
end
|
|
4779
|
-
local recordingId = beginRecording(`Set attribute {attributeName} on {instance.Name}`)
|
|
4780
|
-
local success, result = pcall(function()
|
|
4781
|
-
local value = deserializeValue(attributeValue, valueType)
|
|
4782
|
-
instance:SetAttribute(attributeName, value)
|
|
4783
|
-
return {
|
|
4784
|
-
success = true,
|
|
4785
|
-
instancePath = instancePath,
|
|
4786
|
-
attributeName = attributeName,
|
|
4787
|
-
value = attributeValue,
|
|
4788
|
-
message = "Attribute set successfully",
|
|
4789
|
-
}
|
|
4790
|
-
end)
|
|
4791
|
-
if success then
|
|
4792
|
-
finishRecording(recordingId, true)
|
|
4793
|
-
return result
|
|
4794
|
-
end
|
|
4795
|
-
finishRecording(recordingId, false)
|
|
4796
|
-
return {
|
|
4797
|
-
error = `Failed to set attribute: {result}`,
|
|
4798
|
-
}
|
|
4799
|
-
end
|
|
4800
3572
|
local function getAttributes(requestData)
|
|
4801
3573
|
local instancePath = requestData.instancePath
|
|
4802
3574
|
if not (instancePath ~= "" and instancePath) then
|
|
@@ -4834,175 +3606,6 @@ local function getAttributes(requestData)
|
|
|
4834
3606
|
error = `Failed to get attributes: {result}`,
|
|
4835
3607
|
}
|
|
4836
3608
|
end
|
|
4837
|
-
local function deleteAttribute(requestData)
|
|
4838
|
-
local instancePath = requestData.instancePath
|
|
4839
|
-
local attributeName = requestData.attributeName
|
|
4840
|
-
if not (instancePath ~= "" and instancePath) or not (attributeName ~= "" and attributeName) then
|
|
4841
|
-
return {
|
|
4842
|
-
error = "Instance path and attribute name are required",
|
|
4843
|
-
}
|
|
4844
|
-
end
|
|
4845
|
-
local instance = getInstanceByPath(instancePath)
|
|
4846
|
-
if not instance then
|
|
4847
|
-
return {
|
|
4848
|
-
error = `Instance not found: {instancePath}`,
|
|
4849
|
-
}
|
|
4850
|
-
end
|
|
4851
|
-
local recordingId = beginRecording(`Delete attribute {attributeName} from {instance.Name}`)
|
|
4852
|
-
local success, result = pcall(function()
|
|
4853
|
-
local existed = instance:GetAttribute(attributeName) ~= nil
|
|
4854
|
-
instance:SetAttribute(attributeName, nil)
|
|
4855
|
-
return {
|
|
4856
|
-
success = true,
|
|
4857
|
-
instancePath = instancePath,
|
|
4858
|
-
attributeName = attributeName,
|
|
4859
|
-
existed = existed,
|
|
4860
|
-
message = if existed then "Attribute deleted successfully" else "Attribute did not exist",
|
|
4861
|
-
}
|
|
4862
|
-
end)
|
|
4863
|
-
if success then
|
|
4864
|
-
finishRecording(recordingId, true)
|
|
4865
|
-
return result
|
|
4866
|
-
end
|
|
4867
|
-
finishRecording(recordingId, false)
|
|
4868
|
-
return {
|
|
4869
|
-
error = `Failed to delete attribute: {result}`,
|
|
4870
|
-
}
|
|
4871
|
-
end
|
|
4872
|
-
local function getTags(requestData)
|
|
4873
|
-
local instancePath = requestData.instancePath
|
|
4874
|
-
if not (instancePath ~= "" and instancePath) then
|
|
4875
|
-
return {
|
|
4876
|
-
error = "Instance path is required",
|
|
4877
|
-
}
|
|
4878
|
-
end
|
|
4879
|
-
local instance = getInstanceByPath(instancePath)
|
|
4880
|
-
if not instance then
|
|
4881
|
-
return {
|
|
4882
|
-
error = `Instance not found: {instancePath}`,
|
|
4883
|
-
}
|
|
4884
|
-
end
|
|
4885
|
-
local success, result = pcall(function()
|
|
4886
|
-
local tags = CollectionService:GetTags(instance)
|
|
4887
|
-
return {
|
|
4888
|
-
instancePath = instancePath,
|
|
4889
|
-
tags = tags,
|
|
4890
|
-
count = #tags,
|
|
4891
|
-
}
|
|
4892
|
-
end)
|
|
4893
|
-
if success then
|
|
4894
|
-
return result
|
|
4895
|
-
end
|
|
4896
|
-
return {
|
|
4897
|
-
error = `Failed to get tags: {result}`,
|
|
4898
|
-
}
|
|
4899
|
-
end
|
|
4900
|
-
local function addTag(requestData)
|
|
4901
|
-
local instancePath = requestData.instancePath
|
|
4902
|
-
local tagName = requestData.tagName
|
|
4903
|
-
if not (instancePath ~= "" and instancePath) or not (tagName ~= "" and tagName) then
|
|
4904
|
-
return {
|
|
4905
|
-
error = "Instance path and tag name are required",
|
|
4906
|
-
}
|
|
4907
|
-
end
|
|
4908
|
-
local instance = getInstanceByPath(instancePath)
|
|
4909
|
-
if not instance then
|
|
4910
|
-
return {
|
|
4911
|
-
error = `Instance not found: {instancePath}`,
|
|
4912
|
-
}
|
|
4913
|
-
end
|
|
4914
|
-
local recordingId = beginRecording(`Add tag {tagName} to {instance.Name}`)
|
|
4915
|
-
local success, result = pcall(function()
|
|
4916
|
-
local alreadyHad = CollectionService:HasTag(instance, tagName)
|
|
4917
|
-
CollectionService:AddTag(instance, tagName)
|
|
4918
|
-
return {
|
|
4919
|
-
success = true,
|
|
4920
|
-
instancePath = instancePath,
|
|
4921
|
-
tagName = tagName,
|
|
4922
|
-
alreadyHad = alreadyHad,
|
|
4923
|
-
message = if alreadyHad then "Instance already had this tag" else "Tag added successfully",
|
|
4924
|
-
}
|
|
4925
|
-
end)
|
|
4926
|
-
if success then
|
|
4927
|
-
finishRecording(recordingId, true)
|
|
4928
|
-
return result
|
|
4929
|
-
end
|
|
4930
|
-
finishRecording(recordingId, false)
|
|
4931
|
-
return {
|
|
4932
|
-
error = `Failed to add tag: {result}`,
|
|
4933
|
-
}
|
|
4934
|
-
end
|
|
4935
|
-
local function removeTag(requestData)
|
|
4936
|
-
local instancePath = requestData.instancePath
|
|
4937
|
-
local tagName = requestData.tagName
|
|
4938
|
-
if not (instancePath ~= "" and instancePath) or not (tagName ~= "" and tagName) then
|
|
4939
|
-
return {
|
|
4940
|
-
error = "Instance path and tag name are required",
|
|
4941
|
-
}
|
|
4942
|
-
end
|
|
4943
|
-
local instance = getInstanceByPath(instancePath)
|
|
4944
|
-
if not instance then
|
|
4945
|
-
return {
|
|
4946
|
-
error = `Instance not found: {instancePath}`,
|
|
4947
|
-
}
|
|
4948
|
-
end
|
|
4949
|
-
local recordingId = beginRecording(`Remove tag {tagName} from {instance.Name}`)
|
|
4950
|
-
local success, result = pcall(function()
|
|
4951
|
-
local hadTag = CollectionService:HasTag(instance, tagName)
|
|
4952
|
-
CollectionService:RemoveTag(instance, tagName)
|
|
4953
|
-
return {
|
|
4954
|
-
success = true,
|
|
4955
|
-
instancePath = instancePath,
|
|
4956
|
-
tagName = tagName,
|
|
4957
|
-
hadTag = hadTag,
|
|
4958
|
-
message = if hadTag then "Tag removed successfully" else "Instance did not have this tag",
|
|
4959
|
-
}
|
|
4960
|
-
end)
|
|
4961
|
-
if success then
|
|
4962
|
-
finishRecording(recordingId, true)
|
|
4963
|
-
return result
|
|
4964
|
-
end
|
|
4965
|
-
finishRecording(recordingId, false)
|
|
4966
|
-
return {
|
|
4967
|
-
error = `Failed to remove tag: {result}`,
|
|
4968
|
-
}
|
|
4969
|
-
end
|
|
4970
|
-
local function getTagged(requestData)
|
|
4971
|
-
local tagName = requestData.tagName
|
|
4972
|
-
if not (tagName ~= "" and tagName) then
|
|
4973
|
-
return {
|
|
4974
|
-
error = "Tag name is required",
|
|
4975
|
-
}
|
|
4976
|
-
end
|
|
4977
|
-
local success, result = pcall(function()
|
|
4978
|
-
local taggedInstances = CollectionService:GetTagged(tagName)
|
|
4979
|
-
-- ▼ ReadonlyArray.map ▼
|
|
4980
|
-
local _newValue = table.create(#taggedInstances)
|
|
4981
|
-
local _callback = function(instance)
|
|
4982
|
-
return {
|
|
4983
|
-
name = instance.Name,
|
|
4984
|
-
className = instance.ClassName,
|
|
4985
|
-
path = getInstancePath(instance),
|
|
4986
|
-
}
|
|
4987
|
-
end
|
|
4988
|
-
for _k, _v in taggedInstances do
|
|
4989
|
-
_newValue[_k] = _callback(_v, _k - 1, taggedInstances)
|
|
4990
|
-
end
|
|
4991
|
-
-- ▲ ReadonlyArray.map ▲
|
|
4992
|
-
local instances = _newValue
|
|
4993
|
-
return {
|
|
4994
|
-
tagName = tagName,
|
|
4995
|
-
instances = instances,
|
|
4996
|
-
count = #instances,
|
|
4997
|
-
}
|
|
4998
|
-
end)
|
|
4999
|
-
if success then
|
|
5000
|
-
return result
|
|
5001
|
-
end
|
|
5002
|
-
return {
|
|
5003
|
-
error = `Failed to get tagged instances: {result}`,
|
|
5004
|
-
}
|
|
5005
|
-
end
|
|
5006
3609
|
local function getSelection(_requestData)
|
|
5007
3610
|
local selection = Selection:Get()
|
|
5008
3611
|
if #selection == 0 then
|
|
@@ -5048,106 +3651,15 @@ local function executeLuau(requestData)
|
|
|
5048
3651
|
-- the same code path and produce identical output shapes.
|
|
5049
3652
|
return LuauExec.execute(code)
|
|
5050
3653
|
end
|
|
5051
|
-
local function undo(_requestData)
|
|
5052
|
-
local success, result = pcall(function()
|
|
5053
|
-
ChangeHistoryService:Undo()
|
|
5054
|
-
return {
|
|
5055
|
-
success = true,
|
|
5056
|
-
message = "Undo executed successfully",
|
|
5057
|
-
}
|
|
5058
|
-
end)
|
|
5059
|
-
if success then
|
|
5060
|
-
return result
|
|
5061
|
-
end
|
|
5062
|
-
return {
|
|
5063
|
-
error = `Failed to undo: {result}`,
|
|
5064
|
-
}
|
|
5065
|
-
end
|
|
5066
|
-
local function redo(_requestData)
|
|
5067
|
-
local success, result = pcall(function()
|
|
5068
|
-
ChangeHistoryService:Redo()
|
|
5069
|
-
return {
|
|
5070
|
-
success = true,
|
|
5071
|
-
message = "Redo executed successfully",
|
|
5072
|
-
}
|
|
5073
|
-
end)
|
|
5074
|
-
if success then
|
|
5075
|
-
return result
|
|
5076
|
-
end
|
|
5077
|
-
return {
|
|
5078
|
-
error = `Failed to redo: {result}`,
|
|
5079
|
-
}
|
|
5080
|
-
end
|
|
5081
|
-
local function bulkSetAttributes(requestData)
|
|
5082
|
-
local instancePath = requestData.instancePath
|
|
5083
|
-
local attributes = requestData.attributes
|
|
5084
|
-
if not (instancePath ~= "" and instancePath) or not attributes then
|
|
5085
|
-
return {
|
|
5086
|
-
error = "Instance path and attributes are required",
|
|
5087
|
-
}
|
|
5088
|
-
end
|
|
5089
|
-
local instance = getInstanceByPath(instancePath)
|
|
5090
|
-
if not instance then
|
|
5091
|
-
return {
|
|
5092
|
-
error = `Instance not found: {instancePath}`,
|
|
5093
|
-
}
|
|
5094
|
-
end
|
|
5095
|
-
local recordingId = beginRecording(`Bulk set attributes on {instance.Name}`)
|
|
5096
|
-
local results = {}
|
|
5097
|
-
local successCount = 0
|
|
5098
|
-
local failureCount = 0
|
|
5099
|
-
for name, rawValue in pairs(attributes) do
|
|
5100
|
-
local attrName = name
|
|
5101
|
-
local ok, err = pcall(function()
|
|
5102
|
-
local value = deserializeValue(rawValue)
|
|
5103
|
-
instance:SetAttribute(attrName, value)
|
|
5104
|
-
end)
|
|
5105
|
-
if ok then
|
|
5106
|
-
successCount += 1
|
|
5107
|
-
local _arg0 = {
|
|
5108
|
-
attributeName = attrName,
|
|
5109
|
-
success = true,
|
|
5110
|
-
}
|
|
5111
|
-
table.insert(results, _arg0)
|
|
5112
|
-
else
|
|
5113
|
-
failureCount += 1
|
|
5114
|
-
local _arg0 = {
|
|
5115
|
-
attributeName = attrName,
|
|
5116
|
-
success = false,
|
|
5117
|
-
error = tostring(err),
|
|
5118
|
-
}
|
|
5119
|
-
table.insert(results, _arg0)
|
|
5120
|
-
end
|
|
5121
|
-
end
|
|
5122
|
-
finishRecording(recordingId, successCount > 0)
|
|
5123
|
-
return {
|
|
5124
|
-
instancePath = instancePath,
|
|
5125
|
-
results = results,
|
|
5126
|
-
summary = {
|
|
5127
|
-
total = successCount + failureCount,
|
|
5128
|
-
succeeded = successCount,
|
|
5129
|
-
failed = failureCount,
|
|
5130
|
-
},
|
|
5131
|
-
}
|
|
5132
|
-
end
|
|
5133
3654
|
return {
|
|
5134
|
-
setAttribute = setAttribute,
|
|
5135
3655
|
getAttributes = getAttributes,
|
|
5136
|
-
deleteAttribute = deleteAttribute,
|
|
5137
|
-
getTags = getTags,
|
|
5138
|
-
addTag = addTag,
|
|
5139
|
-
removeTag = removeTag,
|
|
5140
|
-
getTagged = getTagged,
|
|
5141
3656
|
getSelection = getSelection,
|
|
5142
3657
|
executeLuau = executeLuau,
|
|
5143
|
-
undo = undo,
|
|
5144
|
-
redo = redo,
|
|
5145
|
-
bulkSetAttributes = bulkSetAttributes,
|
|
5146
3658
|
}
|
|
5147
3659
|
]]></string>
|
|
5148
3660
|
</Properties>
|
|
5149
3661
|
</Item>
|
|
5150
|
-
<Item class="ModuleScript" referent="
|
|
3662
|
+
<Item class="ModuleScript" referent="16">
|
|
5151
3663
|
<Properties>
|
|
5152
3664
|
<string name="Name">MicroProfilerHandlers</string>
|
|
5153
3665
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -6791,7 +5303,7 @@ return {
|
|
|
6791
5303
|
]]></string>
|
|
6792
5304
|
</Properties>
|
|
6793
5305
|
</Item>
|
|
6794
|
-
<Item class="ModuleScript" referent="
|
|
5306
|
+
<Item class="ModuleScript" referent="17">
|
|
6795
5307
|
<Properties>
|
|
6796
5308
|
<string name="Name">PropertyHandlers</string>
|
|
6797
5309
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -6804,170 +5316,6 @@ local convertPropertyValue = _binding.convertPropertyValue
|
|
|
6804
5316
|
local _binding_1 = Recording
|
|
6805
5317
|
local beginRecording = _binding_1.beginRecording
|
|
6806
5318
|
local finishRecording = _binding_1.finishRecording
|
|
6807
|
-
local function setProperty(requestData)
|
|
6808
|
-
local instancePath = requestData.instancePath
|
|
6809
|
-
local propertyName = requestData.propertyName
|
|
6810
|
-
local propertyValue = requestData.propertyValue
|
|
6811
|
-
if not (instancePath ~= "" and instancePath) or not (propertyName ~= "" and propertyName) then
|
|
6812
|
-
return {
|
|
6813
|
-
error = "Instance path and property name are required",
|
|
6814
|
-
}
|
|
6815
|
-
end
|
|
6816
|
-
local instance = getInstanceByPath(instancePath)
|
|
6817
|
-
if not instance then
|
|
6818
|
-
return {
|
|
6819
|
-
error = `Instance not found: {instancePath}`,
|
|
6820
|
-
}
|
|
6821
|
-
end
|
|
6822
|
-
local recordingId = beginRecording(`Set {propertyName} property`)
|
|
6823
|
-
local inst = instance
|
|
6824
|
-
local success, result = pcall(function()
|
|
6825
|
-
if propertyName == "Parent" or propertyName == "PrimaryPart" then
|
|
6826
|
-
if type(propertyValue) == "string" then
|
|
6827
|
-
local refInstance = getInstanceByPath(propertyValue)
|
|
6828
|
-
if refInstance then
|
|
6829
|
-
inst[propertyName] = refInstance
|
|
6830
|
-
else
|
|
6831
|
-
return {
|
|
6832
|
-
error = `{propertyName} instance not found: {propertyValue}`,
|
|
6833
|
-
}
|
|
6834
|
-
end
|
|
6835
|
-
end
|
|
6836
|
-
elseif propertyName == "Name" then
|
|
6837
|
-
instance.Name = tostring(propertyValue)
|
|
6838
|
-
elseif propertyName == "Source" and instance:IsA("LuaSourceContainer") then
|
|
6839
|
-
instance.Source = tostring(propertyValue)
|
|
6840
|
-
else
|
|
6841
|
-
local convertedValue = convertPropertyValue(instance, propertyName, propertyValue)
|
|
6842
|
-
if convertedValue ~= nil then
|
|
6843
|
-
inst[propertyName] = convertedValue
|
|
6844
|
-
else
|
|
6845
|
-
inst[propertyName] = propertyValue
|
|
6846
|
-
end
|
|
6847
|
-
end
|
|
6848
|
-
return true
|
|
6849
|
-
end)
|
|
6850
|
-
if success then
|
|
6851
|
-
finishRecording(recordingId, true)
|
|
6852
|
-
return {
|
|
6853
|
-
success = true,
|
|
6854
|
-
instancePath = instancePath,
|
|
6855
|
-
propertyName = propertyName,
|
|
6856
|
-
propertyValue = propertyValue,
|
|
6857
|
-
message = "Property set successfully",
|
|
6858
|
-
}
|
|
6859
|
-
else
|
|
6860
|
-
finishRecording(recordingId, false)
|
|
6861
|
-
return {
|
|
6862
|
-
error = `Failed to set property: {result}`,
|
|
6863
|
-
instancePath = instancePath,
|
|
6864
|
-
propertyName = propertyName,
|
|
6865
|
-
}
|
|
6866
|
-
end
|
|
6867
|
-
end
|
|
6868
|
-
local function massSetProperty(requestData)
|
|
6869
|
-
local paths = requestData.paths
|
|
6870
|
-
local propertyName = requestData.propertyName
|
|
6871
|
-
local propertyValue = requestData.propertyValue
|
|
6872
|
-
if not paths or not (type(paths) == "table") or #paths == 0 or not (propertyName ~= "" and propertyName) then
|
|
6873
|
-
return {
|
|
6874
|
-
error = "Paths array and property name are required",
|
|
6875
|
-
}
|
|
6876
|
-
end
|
|
6877
|
-
local results = {}
|
|
6878
|
-
local successCount = 0
|
|
6879
|
-
local failureCount = 0
|
|
6880
|
-
local recordingId = beginRecording(`Mass set {propertyName} property`)
|
|
6881
|
-
for _, path in paths do
|
|
6882
|
-
local instance = getInstanceByPath(path)
|
|
6883
|
-
if instance then
|
|
6884
|
-
local success, err = pcall(function()
|
|
6885
|
-
local converted = convertPropertyValue(instance, propertyName, propertyValue)
|
|
6886
|
-
instance[propertyName] = if converted ~= nil then converted else propertyValue
|
|
6887
|
-
end)
|
|
6888
|
-
if success then
|
|
6889
|
-
successCount += 1
|
|
6890
|
-
local _arg0 = {
|
|
6891
|
-
path = path,
|
|
6892
|
-
success = true,
|
|
6893
|
-
propertyName = propertyName,
|
|
6894
|
-
propertyValue = propertyValue,
|
|
6895
|
-
}
|
|
6896
|
-
table.insert(results, _arg0)
|
|
6897
|
-
else
|
|
6898
|
-
failureCount += 1
|
|
6899
|
-
local _arg0 = {
|
|
6900
|
-
path = path,
|
|
6901
|
-
success = false,
|
|
6902
|
-
error = tostring(err),
|
|
6903
|
-
}
|
|
6904
|
-
table.insert(results, _arg0)
|
|
6905
|
-
end
|
|
6906
|
-
else
|
|
6907
|
-
failureCount += 1
|
|
6908
|
-
local _arg0 = {
|
|
6909
|
-
path = path,
|
|
6910
|
-
success = false,
|
|
6911
|
-
error = "Instance not found",
|
|
6912
|
-
}
|
|
6913
|
-
table.insert(results, _arg0)
|
|
6914
|
-
end
|
|
6915
|
-
end
|
|
6916
|
-
finishRecording(recordingId, successCount > 0)
|
|
6917
|
-
return {
|
|
6918
|
-
results = results,
|
|
6919
|
-
summary = {
|
|
6920
|
-
total = #paths,
|
|
6921
|
-
succeeded = successCount,
|
|
6922
|
-
failed = failureCount,
|
|
6923
|
-
},
|
|
6924
|
-
}
|
|
6925
|
-
end
|
|
6926
|
-
local function massGetProperty(requestData)
|
|
6927
|
-
local paths = requestData.paths
|
|
6928
|
-
local propertyName = requestData.propertyName
|
|
6929
|
-
if not paths or not (type(paths) == "table") or #paths == 0 or not (propertyName ~= "" and propertyName) then
|
|
6930
|
-
return {
|
|
6931
|
-
error = "Paths array and property name are required",
|
|
6932
|
-
}
|
|
6933
|
-
end
|
|
6934
|
-
local results = {}
|
|
6935
|
-
for _, path in paths do
|
|
6936
|
-
local instance = getInstanceByPath(path)
|
|
6937
|
-
if instance then
|
|
6938
|
-
local success, value = pcall(function()
|
|
6939
|
-
return instance[propertyName]
|
|
6940
|
-
end)
|
|
6941
|
-
if success then
|
|
6942
|
-
local _arg0 = {
|
|
6943
|
-
path = path,
|
|
6944
|
-
success = true,
|
|
6945
|
-
propertyName = propertyName,
|
|
6946
|
-
propertyValue = value,
|
|
6947
|
-
}
|
|
6948
|
-
table.insert(results, _arg0)
|
|
6949
|
-
else
|
|
6950
|
-
local _arg0 = {
|
|
6951
|
-
path = path,
|
|
6952
|
-
success = false,
|
|
6953
|
-
error = tostring(value),
|
|
6954
|
-
}
|
|
6955
|
-
table.insert(results, _arg0)
|
|
6956
|
-
end
|
|
6957
|
-
else
|
|
6958
|
-
local _arg0 = {
|
|
6959
|
-
path = path,
|
|
6960
|
-
success = false,
|
|
6961
|
-
error = "Instance not found",
|
|
6962
|
-
}
|
|
6963
|
-
table.insert(results, _arg0)
|
|
6964
|
-
end
|
|
6965
|
-
end
|
|
6966
|
-
return {
|
|
6967
|
-
results = results,
|
|
6968
|
-
propertyName = propertyName,
|
|
6969
|
-
}
|
|
6970
|
-
end
|
|
6971
5319
|
local function setProperties(requestData)
|
|
6972
5320
|
local instancePath = requestData.instancePath
|
|
6973
5321
|
local properties = requestData.properties
|
|
@@ -7035,15 +5383,12 @@ local function setProperties(requestData)
|
|
|
7035
5383
|
}
|
|
7036
5384
|
end
|
|
7037
5385
|
return {
|
|
7038
|
-
setProperty = setProperty,
|
|
7039
|
-
massSetProperty = massSetProperty,
|
|
7040
|
-
massGetProperty = massGetProperty,
|
|
7041
5386
|
setProperties = setProperties,
|
|
7042
5387
|
}
|
|
7043
5388
|
]]></string>
|
|
7044
5389
|
</Properties>
|
|
7045
5390
|
</Item>
|
|
7046
|
-
<Item class="ModuleScript" referent="
|
|
5391
|
+
<Item class="ModuleScript" referent="18">
|
|
7047
5392
|
<Properties>
|
|
7048
5393
|
<string name="Name">QueryHandlers</string>
|
|
7049
5394
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -7177,48 +5522,6 @@ local function getPlaceInfo(_requestData)
|
|
|
7177
5522
|
},
|
|
7178
5523
|
}
|
|
7179
5524
|
end
|
|
7180
|
-
local function getServices(requestData)
|
|
7181
|
-
local serviceName = requestData.serviceName
|
|
7182
|
-
if serviceName ~= "" and serviceName then
|
|
7183
|
-
local ok, service = pcall(function()
|
|
7184
|
-
return game:GetService(serviceName)
|
|
7185
|
-
end)
|
|
7186
|
-
if ok and service then
|
|
7187
|
-
return {
|
|
7188
|
-
service = {
|
|
7189
|
-
name = service.Name,
|
|
7190
|
-
className = service.ClassName,
|
|
7191
|
-
path = getInstancePath(service),
|
|
7192
|
-
childCount = #service:GetChildren(),
|
|
7193
|
-
},
|
|
7194
|
-
}
|
|
7195
|
-
else
|
|
7196
|
-
return {
|
|
7197
|
-
error = `Service not found: {serviceName}`,
|
|
7198
|
-
}
|
|
7199
|
-
end
|
|
7200
|
-
else
|
|
7201
|
-
local services = {}
|
|
7202
|
-
local commonServices = { "Workspace", "Players", "StarterGui", "StarterPack", "StarterPlayer", "ReplicatedStorage", "ServerStorage", "ServerScriptService", "HttpService", "TeleportService", "DataStoreService" }
|
|
7203
|
-
for _, svcName in commonServices do
|
|
7204
|
-
local ok, service = pcall(function()
|
|
7205
|
-
return game:GetService(svcName)
|
|
7206
|
-
end)
|
|
7207
|
-
if ok and service then
|
|
7208
|
-
local _arg0 = {
|
|
7209
|
-
name = service.Name,
|
|
7210
|
-
className = service.ClassName,
|
|
7211
|
-
path = getInstancePath(service),
|
|
7212
|
-
childCount = #service:GetChildren(),
|
|
7213
|
-
}
|
|
7214
|
-
table.insert(services, _arg0)
|
|
7215
|
-
end
|
|
7216
|
-
end
|
|
7217
|
-
return {
|
|
7218
|
-
services = services,
|
|
7219
|
-
}
|
|
7220
|
-
end
|
|
7221
|
-
end
|
|
7222
5525
|
local function searchObjects(requestData)
|
|
7223
5526
|
local query = requestData.query
|
|
7224
5527
|
local _condition = (requestData.searchType)
|
|
@@ -7397,39 +5700,6 @@ local function getInstanceProperties(requestData)
|
|
|
7397
5700
|
}
|
|
7398
5701
|
end
|
|
7399
5702
|
end
|
|
7400
|
-
local function getInstanceChildren(requestData)
|
|
7401
|
-
local instancePath = requestData.instancePath
|
|
7402
|
-
if not (instancePath ~= "" and instancePath) then
|
|
7403
|
-
return {
|
|
7404
|
-
error = "Instance path is required",
|
|
7405
|
-
}
|
|
7406
|
-
end
|
|
7407
|
-
local instance = getInstanceByPath(instancePath)
|
|
7408
|
-
if not instance then
|
|
7409
|
-
return {
|
|
7410
|
-
error = `Instance not found: {instancePath}`,
|
|
7411
|
-
}
|
|
7412
|
-
end
|
|
7413
|
-
local children = {}
|
|
7414
|
-
for _, child in instance:GetChildren() do
|
|
7415
|
-
local entry = {
|
|
7416
|
-
name = child.Name,
|
|
7417
|
-
className = child.ClassName,
|
|
7418
|
-
path = getInstancePath(child),
|
|
7419
|
-
hasChildren = #child:GetChildren() > 0,
|
|
7420
|
-
hasSource = child:IsA("LuaSourceContainer"),
|
|
7421
|
-
}
|
|
7422
|
-
if child:IsA("BaseScript") then
|
|
7423
|
-
entry.enabled = child.Enabled
|
|
7424
|
-
end
|
|
7425
|
-
table.insert(children, entry)
|
|
7426
|
-
end
|
|
7427
|
-
return {
|
|
7428
|
-
instancePath = instancePath,
|
|
7429
|
-
children = children,
|
|
7430
|
-
count = #children,
|
|
7431
|
-
}
|
|
7432
|
-
end
|
|
7433
5703
|
local function searchByProperty(requestData)
|
|
7434
5704
|
local propertyName = requestData.propertyName
|
|
7435
5705
|
local propertyValue = requestData.propertyValue
|
|
@@ -7974,133 +6244,21 @@ local function grepScripts(requestData)
|
|
|
7974
6244
|
},
|
|
7975
6245
|
}
|
|
7976
6246
|
end
|
|
7977
|
-
local function getDescendants(requestData)
|
|
7978
|
-
local instancePath = requestData.instancePath
|
|
7979
|
-
if not (instancePath ~= "" and instancePath) then
|
|
7980
|
-
return {
|
|
7981
|
-
error = "Instance path is required",
|
|
7982
|
-
}
|
|
7983
|
-
end
|
|
7984
|
-
local _condition = (requestData.maxDepth)
|
|
7985
|
-
if _condition == nil then
|
|
7986
|
-
_condition = 10
|
|
7987
|
-
end
|
|
7988
|
-
local maxDepth = _condition
|
|
7989
|
-
local classFilter = requestData.classFilter
|
|
7990
|
-
local instance = getInstanceByPath(instancePath)
|
|
7991
|
-
if not instance then
|
|
7992
|
-
return {
|
|
7993
|
-
error = `Instance not found: {instancePath}`,
|
|
7994
|
-
}
|
|
7995
|
-
end
|
|
7996
|
-
local descendants = {}
|
|
7997
|
-
local function collect(inst, depth)
|
|
7998
|
-
if depth > maxDepth then
|
|
7999
|
-
return nil
|
|
8000
|
-
end
|
|
8001
|
-
for _, child in inst:GetChildren() do
|
|
8002
|
-
local _condition_1 = classFilter
|
|
8003
|
-
if _condition_1 ~= "" and _condition_1 then
|
|
8004
|
-
_condition_1 = not child:IsA(classFilter)
|
|
8005
|
-
end
|
|
8006
|
-
if _condition_1 ~= "" and _condition_1 then
|
|
8007
|
-
continue
|
|
8008
|
-
end
|
|
8009
|
-
local _arg0 = {
|
|
8010
|
-
name = child.Name,
|
|
8011
|
-
className = child.ClassName,
|
|
8012
|
-
path = getInstancePath(child),
|
|
8013
|
-
depth = depth,
|
|
8014
|
-
}
|
|
8015
|
-
table.insert(descendants, _arg0)
|
|
8016
|
-
collect(child, depth + 1)
|
|
8017
|
-
end
|
|
8018
|
-
end
|
|
8019
|
-
collect(instance, 1)
|
|
8020
|
-
return {
|
|
8021
|
-
instancePath = instancePath,
|
|
8022
|
-
descendants = descendants,
|
|
8023
|
-
count = #descendants,
|
|
8024
|
-
maxDepth = maxDepth,
|
|
8025
|
-
}
|
|
8026
|
-
end
|
|
8027
|
-
local function compareInstances(requestData)
|
|
8028
|
-
local instancePathA = requestData.instancePathA
|
|
8029
|
-
local instancePathB = requestData.instancePathB
|
|
8030
|
-
if not (instancePathA ~= "" and instancePathA) or not (instancePathB ~= "" and instancePathB) then
|
|
8031
|
-
return {
|
|
8032
|
-
error = "Both instancePathA and instancePathB are required",
|
|
8033
|
-
}
|
|
8034
|
-
end
|
|
8035
|
-
local instA = getInstanceByPath(instancePathA)
|
|
8036
|
-
if not instA then
|
|
8037
|
-
return {
|
|
8038
|
-
error = `Instance not found: {instancePathA}`,
|
|
8039
|
-
}
|
|
8040
|
-
end
|
|
8041
|
-
local instB = getInstanceByPath(instancePathB)
|
|
8042
|
-
if not instB then
|
|
8043
|
-
return {
|
|
8044
|
-
error = `Instance not found: {instancePathB}`,
|
|
8045
|
-
}
|
|
8046
|
-
end
|
|
8047
|
-
local commonProps = { "Name", "ClassName", "Size", "Position", "Rotation", "CFrame", "Anchored", "CanCollide", "Transparency", "BrickColor", "Material", "Color", "Text", "TextColor3", "BackgroundColor3", "Image", "ImageColor3", "Visible", "Active", "ZIndex", "BorderSizePixel", "BackgroundTransparency", "ImageTransparency", "TextTransparency", "Value", "Enabled", "Brightness", "Range", "Shadows" }
|
|
8048
|
-
local matching = {}
|
|
8049
|
-
local differing = {}
|
|
8050
|
-
local onlyA = {}
|
|
8051
|
-
local onlyB = {}
|
|
8052
|
-
for _, prop in commonProps do
|
|
8053
|
-
local okA, valA = pcall(function()
|
|
8054
|
-
return tostring(instA[prop])
|
|
8055
|
-
end)
|
|
8056
|
-
local okB, valB = pcall(function()
|
|
8057
|
-
return tostring(instB[prop])
|
|
8058
|
-
end)
|
|
8059
|
-
if okA and okB then
|
|
8060
|
-
if valA == valB then
|
|
8061
|
-
matching[prop] = valA
|
|
8062
|
-
else
|
|
8063
|
-
differing[prop] = {
|
|
8064
|
-
a = valA,
|
|
8065
|
-
b = valB,
|
|
8066
|
-
}
|
|
8067
|
-
end
|
|
8068
|
-
elseif okA then
|
|
8069
|
-
table.insert(onlyA, prop)
|
|
8070
|
-
elseif okB then
|
|
8071
|
-
table.insert(onlyB, prop)
|
|
8072
|
-
end
|
|
8073
|
-
end
|
|
8074
|
-
return {
|
|
8075
|
-
instancePathA = instancePathA,
|
|
8076
|
-
instancePathB = instancePathB,
|
|
8077
|
-
classNameA = instA.ClassName,
|
|
8078
|
-
classNameB = instB.ClassName,
|
|
8079
|
-
matching = matching,
|
|
8080
|
-
differing = differing,
|
|
8081
|
-
onlyA = onlyA,
|
|
8082
|
-
onlyB = onlyB,
|
|
8083
|
-
}
|
|
8084
|
-
end
|
|
8085
6247
|
return {
|
|
8086
6248
|
getFileTree = getFileTree,
|
|
8087
6249
|
searchFiles = searchFiles,
|
|
8088
6250
|
getPlaceInfo = getPlaceInfo,
|
|
8089
|
-
getServices = getServices,
|
|
8090
6251
|
searchObjects = searchObjects,
|
|
8091
6252
|
getInstanceProperties = getInstanceProperties,
|
|
8092
|
-
getInstanceChildren = getInstanceChildren,
|
|
8093
6253
|
searchByProperty = searchByProperty,
|
|
8094
6254
|
getClassInfo = getClassInfo,
|
|
8095
6255
|
getProjectStructure = getProjectStructure,
|
|
8096
6256
|
grepScripts = grepScripts,
|
|
8097
|
-
getDescendants = getDescendants,
|
|
8098
|
-
compareInstances = compareInstances,
|
|
8099
6257
|
}
|
|
8100
6258
|
]]></string>
|
|
8101
6259
|
</Properties>
|
|
8102
6260
|
</Item>
|
|
8103
|
-
<Item class="ModuleScript" referent="
|
|
6261
|
+
<Item class="ModuleScript" referent="19">
|
|
8104
6262
|
<Properties>
|
|
8105
6263
|
<string name="Name">SceneAnalysisHandlers</string>
|
|
8106
6264
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -8349,18 +6507,18 @@ return {
|
|
|
8349
6507
|
]]></string>
|
|
8350
6508
|
</Properties>
|
|
8351
6509
|
</Item>
|
|
8352
|
-
<Item class="ModuleScript" referent="
|
|
6510
|
+
<Item class="ModuleScript" referent="20">
|
|
8353
6511
|
<Properties>
|
|
8354
6512
|
<string name="Name">ScriptHandlers</string>
|
|
8355
6513
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
8356
6514
|
local TS = require(script.Parent.Parent.Parent.include.RuntimeLib)
|
|
8357
6515
|
local Utils = TS.import(script, script.Parent.Parent, "Utils")
|
|
8358
6516
|
local Recording = TS.import(script, script.Parent.Parent, "Recording")
|
|
8359
|
-
local ScriptEditorService = game:GetService("ScriptEditorService")
|
|
8360
6517
|
local _binding = Utils
|
|
8361
6518
|
local getInstancePath = _binding.getInstancePath
|
|
8362
6519
|
local getInstanceByPath = _binding.getInstanceByPath
|
|
8363
6520
|
local readScriptSource = _binding.readScriptSource
|
|
6521
|
+
local applyScriptSource = _binding.applyScriptSource
|
|
8364
6522
|
local splitLines = _binding.splitLines
|
|
8365
6523
|
local joinLines = _binding.joinLines
|
|
8366
6524
|
local _binding_1 = Recording
|
|
@@ -8524,42 +6682,27 @@ local function setScriptSource(requestData)
|
|
|
8524
6682
|
end
|
|
8525
6683
|
local sourceToSet = normalizeEscapes(newSource)
|
|
8526
6684
|
local recordingId = beginRecording(`Set script source: {instance.Name}`)
|
|
8527
|
-
local
|
|
8528
|
-
|
|
8529
|
-
|
|
8530
|
-
|
|
8531
|
-
|
|
8532
|
-
if readScriptSource(instance) ~= sourceToSet then
|
|
8533
|
-
error("UpdateSourceAsync completed without updating the script source")
|
|
8534
|
-
end
|
|
6685
|
+
local readSuccess, readResult = pcall(function()
|
|
6686
|
+
return #readScriptSource(instance)
|
|
6687
|
+
end)
|
|
6688
|
+
if not readSuccess then
|
|
6689
|
+
finishRecording(recordingId, false)
|
|
8535
6690
|
return {
|
|
8536
|
-
|
|
8537
|
-
instancePath = instancePath,
|
|
8538
|
-
oldSourceLength = oldSourceLength,
|
|
8539
|
-
newSourceLength = #sourceToSet,
|
|
8540
|
-
method = "UpdateSourceAsync",
|
|
8541
|
-
message = "Script source updated successfully (editor-safe)",
|
|
6691
|
+
error = `Failed to read script source before updating: {readResult}`,
|
|
8542
6692
|
}
|
|
8543
|
-
end)
|
|
8544
|
-
if updateSuccess then
|
|
8545
|
-
finishRecording(recordingId, true)
|
|
8546
|
-
return updateResult
|
|
8547
6693
|
end
|
|
8548
|
-
local
|
|
8549
|
-
|
|
8550
|
-
|
|
6694
|
+
local oldSourceLength = readResult
|
|
6695
|
+
local applyResult = applyScriptSource(instance, sourceToSet)
|
|
6696
|
+
if applyResult.success then
|
|
6697
|
+
finishRecording(recordingId, true)
|
|
8551
6698
|
return {
|
|
8552
6699
|
success = true,
|
|
8553
6700
|
instancePath = instancePath,
|
|
8554
|
-
oldSourceLength =
|
|
6701
|
+
oldSourceLength = oldSourceLength,
|
|
8555
6702
|
newSourceLength = #sourceToSet,
|
|
8556
|
-
method =
|
|
8557
|
-
message =
|
|
6703
|
+
method = applyResult.method,
|
|
6704
|
+
message = `Script source updated successfully ({if applyResult.method == "UpdateSourceAsync" then "editor-safe" else "direct assignment"})`,
|
|
8558
6705
|
}
|
|
8559
|
-
end)
|
|
8560
|
-
if directSuccess then
|
|
8561
|
-
finishRecording(recordingId, true)
|
|
8562
|
-
return directResult
|
|
8563
6706
|
end
|
|
8564
6707
|
local replaceSuccess, replaceResult = pcall(function()
|
|
8565
6708
|
local parent = instance.Parent
|
|
@@ -8569,9 +6712,15 @@ local function setScriptSource(requestData)
|
|
|
8569
6712
|
local enabled = if wasBaseScript then instance.Enabled else nil
|
|
8570
6713
|
local newScript = Instance.new(className)
|
|
8571
6714
|
newScript.Name = name
|
|
8572
|
-
|
|
6715
|
+
-- @rbxts/types does not expose PluginSecurity Source writes.
|
|
6716
|
+
local writableNewScript = newScript
|
|
6717
|
+
writableNewScript.Source = sourceToSet
|
|
6718
|
+
if readScriptSource(newScript) ~= sourceToSet then
|
|
6719
|
+
error("Replacement script source did not match the requested source")
|
|
6720
|
+
end
|
|
8573
6721
|
if wasBaseScript and enabled ~= nil then
|
|
8574
|
-
|
|
6722
|
+
local newBaseScript = newScript
|
|
6723
|
+
newBaseScript.Enabled = enabled
|
|
8575
6724
|
end
|
|
8576
6725
|
newScript.Parent = parent
|
|
8577
6726
|
instance:Destroy()
|
|
@@ -8588,7 +6737,7 @@ local function setScriptSource(requestData)
|
|
|
8588
6737
|
end
|
|
8589
6738
|
finishRecording(recordingId, false)
|
|
8590
6739
|
return {
|
|
8591
|
-
error = `Failed to set script source.
|
|
6740
|
+
error = `Failed to set script source. {applyResult.error} Replace method failed: {replaceResult}`,
|
|
8592
6741
|
}
|
|
8593
6742
|
end
|
|
8594
6743
|
local function editScriptLines(requestData)
|
|
@@ -8666,12 +6815,14 @@ local function editScriptLines(requestData)
|
|
|
8666
6815
|
end
|
|
8667
6816
|
-- Byte-slice replacement avoids Lua pattern escaping (safe for multi-byte chars like em dashes).
|
|
8668
6817
|
local newSource = string.sub(source, 1, matchStart - 1) .. newString .. string.sub(source, matchStart + searchLen)
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
6818
|
+
local applyResult = applyScriptSource(instance, newSource, source)
|
|
6819
|
+
if not applyResult.success then
|
|
6820
|
+
error(applyResult.error)
|
|
6821
|
+
end
|
|
8672
6822
|
return {
|
|
8673
6823
|
success = true,
|
|
8674
6824
|
instancePath = instancePath,
|
|
6825
|
+
method = applyResult.method,
|
|
8675
6826
|
message = "Script edited successfully",
|
|
8676
6827
|
}
|
|
8677
6828
|
end)
|
|
@@ -8711,7 +6862,8 @@ local function insertScriptLines(requestData)
|
|
|
8711
6862
|
end
|
|
8712
6863
|
local recordingId = beginRecording(`Insert script lines after line {afterLine}: {instance.Name}`)
|
|
8713
6864
|
local success, result = pcall(function()
|
|
8714
|
-
local
|
|
6865
|
+
local source = readScriptSource(instance)
|
|
6866
|
+
local lines, hadTrailingNewline = splitLines(source)
|
|
8715
6867
|
local totalLines = #lines
|
|
8716
6868
|
if afterLine < 0 or afterLine > totalLines then
|
|
8717
6869
|
error(`afterLine out of range (0-{totalLines})`)
|
|
@@ -8754,15 +6906,17 @@ local function insertScriptLines(requestData)
|
|
|
8754
6906
|
end
|
|
8755
6907
|
end
|
|
8756
6908
|
local newSource = joinLines(resultLines, hadTrailingNewline)
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
6909
|
+
local applyResult = applyScriptSource(instance, newSource, source)
|
|
6910
|
+
if not applyResult.success then
|
|
6911
|
+
error(applyResult.error)
|
|
6912
|
+
end
|
|
8760
6913
|
return {
|
|
8761
6914
|
success = true,
|
|
8762
6915
|
instancePath = instancePath,
|
|
8763
6916
|
insertedAfterLine = afterLine,
|
|
8764
6917
|
linesInserted = #newLines,
|
|
8765
6918
|
newLineCount = #resultLines,
|
|
6919
|
+
method = applyResult.method,
|
|
8766
6920
|
message = "Script lines inserted successfully",
|
|
8767
6921
|
}
|
|
8768
6922
|
end)
|
|
@@ -8797,7 +6951,8 @@ local function deleteScriptLines(requestData)
|
|
|
8797
6951
|
end
|
|
8798
6952
|
local recordingId = beginRecording(`Delete script lines {startLine}-{endLine}: {instance.Name}`)
|
|
8799
6953
|
local success, result = pcall(function()
|
|
8800
|
-
local
|
|
6954
|
+
local source = readScriptSource(instance)
|
|
6955
|
+
local lines, hadTrailingNewline = splitLines(source)
|
|
8801
6956
|
local totalLines = #lines
|
|
8802
6957
|
if startLine < 1 or startLine > totalLines then
|
|
8803
6958
|
error(`startLine out of range (1-{totalLines})`)
|
|
@@ -8839,9 +6994,10 @@ local function deleteScriptLines(requestData)
|
|
|
8839
6994
|
end
|
|
8840
6995
|
end
|
|
8841
6996
|
local newSource = joinLines(resultLines, hadTrailingNewline)
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
|
|
6997
|
+
local applyResult = applyScriptSource(instance, newSource, source)
|
|
6998
|
+
if not applyResult.success then
|
|
6999
|
+
error(applyResult.error)
|
|
7000
|
+
end
|
|
8845
7001
|
return {
|
|
8846
7002
|
success = true,
|
|
8847
7003
|
instancePath = instancePath,
|
|
@@ -8851,6 +7007,7 @@ local function deleteScriptLines(requestData)
|
|
|
8851
7007
|
},
|
|
8852
7008
|
linesDeleted = endLine - startLine + 1,
|
|
8853
7009
|
newLineCount = #resultLines,
|
|
7010
|
+
method = applyResult.method,
|
|
8854
7011
|
message = "Script lines deleted successfully",
|
|
8855
7012
|
}
|
|
8856
7013
|
end)
|
|
@@ -8953,17 +7110,14 @@ local function findAndReplaceInScripts(requestData)
|
|
|
8953
7110
|
if hitLimit then
|
|
8954
7111
|
return nil
|
|
8955
7112
|
end
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
if _condition_5 ~= "" and _condition_5 then
|
|
8965
|
-
return nil
|
|
8966
|
-
end
|
|
7113
|
+
local _condition_5 = classFilter == nil
|
|
7114
|
+
if not _condition_5 then
|
|
7115
|
+
local _exp = string.lower(instance.ClassName)
|
|
7116
|
+
local _arg0 = string.lower(classFilter)
|
|
7117
|
+
_condition_5 = (string.find(_exp, _arg0)) ~= nil
|
|
7118
|
+
end
|
|
7119
|
+
local matchesClass = _condition_5
|
|
7120
|
+
if instance:IsA("LuaSourceContainer") and matchesClass then
|
|
8967
7121
|
scriptsSearched += 1
|
|
8968
7122
|
local source = readScriptSource(instance)
|
|
8969
7123
|
local newSource
|
|
@@ -8988,24 +7142,31 @@ local function findAndReplaceInScripts(requestData)
|
|
|
8988
7142
|
hitLimit = true
|
|
8989
7143
|
return nil
|
|
8990
7144
|
end
|
|
8991
|
-
|
|
8992
|
-
if not
|
|
8993
|
-
local
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
7145
|
+
local applyResult = if dryRun then nil else applyScriptSource(instance, newSource, source)
|
|
7146
|
+
if applyResult ~= nil and not applyResult.success then
|
|
7147
|
+
local _object = {
|
|
7148
|
+
instancePath = getInstancePath(instance),
|
|
7149
|
+
name = instance.Name,
|
|
7150
|
+
className = instance.ClassName,
|
|
7151
|
+
replacements = 0,
|
|
7152
|
+
}
|
|
7153
|
+
local _left = "error"
|
|
7154
|
+
local _condition_6 = applyResult.error
|
|
7155
|
+
if _condition_6 == nil then
|
|
7156
|
+
_condition_6 = "Script write failed verification"
|
|
9000
7157
|
end
|
|
7158
|
+
_object[_left] = _condition_6
|
|
7159
|
+
table.insert(changes, _object)
|
|
7160
|
+
else
|
|
7161
|
+
totalReplacements += replCount
|
|
7162
|
+
local _arg0 = {
|
|
7163
|
+
instancePath = getInstancePath(instance),
|
|
7164
|
+
name = instance.Name,
|
|
7165
|
+
className = instance.ClassName,
|
|
7166
|
+
replacements = replCount,
|
|
7167
|
+
}
|
|
7168
|
+
table.insert(changes, _arg0)
|
|
9001
7169
|
end
|
|
9002
|
-
local _arg0 = {
|
|
9003
|
-
instancePath = getInstancePath(instance),
|
|
9004
|
-
name = instance.Name,
|
|
9005
|
-
className = instance.ClassName,
|
|
9006
|
-
replacements = replCount,
|
|
9007
|
-
}
|
|
9008
|
-
table.insert(changes, _arg0)
|
|
9009
7170
|
end
|
|
9010
7171
|
end
|
|
9011
7172
|
for _, child in instance:GetChildren() do
|
|
@@ -9015,18 +7176,37 @@ local function findAndReplaceInScripts(requestData)
|
|
|
9015
7176
|
processInstance(child)
|
|
9016
7177
|
end
|
|
9017
7178
|
end
|
|
9018
|
-
|
|
7179
|
+
local traversalSuccess, traversalResult = pcall(function()
|
|
7180
|
+
return processInstance(startInstance)
|
|
7181
|
+
end)
|
|
7182
|
+
-- ▼ ReadonlyArray.filter ▼
|
|
7183
|
+
local _newValue = {}
|
|
7184
|
+
local _callback = function(change)
|
|
7185
|
+
return change.error ~= nil
|
|
7186
|
+
end
|
|
7187
|
+
local _length = 0
|
|
7188
|
+
for _k, _v in changes do
|
|
7189
|
+
if _callback(_v, _k - 1, changes) == true then
|
|
7190
|
+
_length += 1
|
|
7191
|
+
_newValue[_length] = _v
|
|
7192
|
+
end
|
|
7193
|
+
end
|
|
7194
|
+
-- ▲ ReadonlyArray.filter ▲
|
|
7195
|
+
local failedScripts = #_newValue
|
|
7196
|
+
local scriptsModified = #changes - failedScripts
|
|
9019
7197
|
if recordingId ~= nil then
|
|
9020
|
-
finishRecording(recordingId,
|
|
7198
|
+
finishRecording(recordingId, scriptsModified > 0)
|
|
9021
7199
|
end
|
|
9022
7200
|
return {
|
|
9023
|
-
success =
|
|
7201
|
+
success = traversalSuccess and failedScripts == 0,
|
|
7202
|
+
error = if traversalSuccess then nil else `Script traversal failed: {traversalResult}`,
|
|
9024
7203
|
dryRun = dryRun,
|
|
9025
7204
|
pattern = searchPattern,
|
|
9026
7205
|
replacement = replacement,
|
|
9027
7206
|
totalReplacements = totalReplacements,
|
|
9028
7207
|
scriptsSearched = scriptsSearched,
|
|
9029
|
-
scriptsModified =
|
|
7208
|
+
scriptsModified = scriptsModified,
|
|
7209
|
+
scriptsFailed = failedScripts,
|
|
9030
7210
|
changes = changes,
|
|
9031
7211
|
truncated = hitLimit,
|
|
9032
7212
|
}
|
|
@@ -9042,7 +7222,7 @@ return {
|
|
|
9042
7222
|
]]></string>
|
|
9043
7223
|
</Properties>
|
|
9044
7224
|
</Item>
|
|
9045
|
-
<Item class="ModuleScript" referent="
|
|
7225
|
+
<Item class="ModuleScript" referent="21">
|
|
9046
7226
|
<Properties>
|
|
9047
7227
|
<string name="Name">ScriptProfilerHandlers</string>
|
|
9048
7228
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -9505,7 +7685,7 @@ return {
|
|
|
9505
7685
|
]]></string>
|
|
9506
7686
|
</Properties>
|
|
9507
7687
|
</Item>
|
|
9508
|
-
<Item class="ModuleScript" referent="
|
|
7688
|
+
<Item class="ModuleScript" referent="22">
|
|
9509
7689
|
<Properties>
|
|
9510
7690
|
<string name="Name">SerializationHandlers</string>
|
|
9511
7691
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -9691,7 +7871,7 @@ return {
|
|
|
9691
7871
|
]]></string>
|
|
9692
7872
|
</Properties>
|
|
9693
7873
|
</Item>
|
|
9694
|
-
<Item class="ModuleScript" referent="
|
|
7874
|
+
<Item class="ModuleScript" referent="23">
|
|
9695
7875
|
<Properties>
|
|
9696
7876
|
<string name="Name">TestHandlers</string>
|
|
9697
7877
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -10036,13 +8216,25 @@ local function multiplayerTestLeaveClient(_requestData)
|
|
|
10036
8216
|
localPlayer = localPlayer,
|
|
10037
8217
|
}
|
|
10038
8218
|
end
|
|
10039
|
-
local function multiplayerTestEnd(
|
|
8219
|
+
local function multiplayerTestEnd(requestData)
|
|
8220
|
+
if not RunService:IsRunning() or not RunService:IsServer() then
|
|
8221
|
+
return {
|
|
8222
|
+
error = "multiplayer_test_end must be called on the running server peer. Route with target=server.",
|
|
8223
|
+
}
|
|
8224
|
+
end
|
|
8225
|
+
local value = if requestData.value ~= nil then requestData.value else "ended_by_mcp"
|
|
8226
|
+
local ok, result = pcall(function()
|
|
8227
|
+
return StudioTestService:EndTest(value)
|
|
8228
|
+
end)
|
|
8229
|
+
if not ok then
|
|
8230
|
+
return {
|
|
8231
|
+
error = tostring(result),
|
|
8232
|
+
}
|
|
8233
|
+
end
|
|
10040
8234
|
return {
|
|
10041
|
-
success =
|
|
10042
|
-
|
|
10043
|
-
|
|
10044
|
-
reason = "StudioTestService:EndTest does not reliably end StudioTestService multiplayer sessions from MCP right now.",
|
|
10045
|
-
manualCleanupRequired = true,
|
|
8235
|
+
success = true,
|
|
8236
|
+
message = "Multiplayer Studio test end requested.",
|
|
8237
|
+
value = value,
|
|
10046
8238
|
}
|
|
10047
8239
|
end
|
|
10048
8240
|
return {
|
|
@@ -10058,7 +8250,7 @@ return {
|
|
|
10058
8250
|
</Properties>
|
|
10059
8251
|
</Item>
|
|
10060
8252
|
</Item>
|
|
10061
|
-
<Item class="ModuleScript" referent="
|
|
8253
|
+
<Item class="ModuleScript" referent="24">
|
|
10062
8254
|
<Properties>
|
|
10063
8255
|
<string name="Name">HttpDiagnostics</string>
|
|
10064
8256
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -10139,7 +8331,7 @@ return {
|
|
|
10139
8331
|
]]></string>
|
|
10140
8332
|
</Properties>
|
|
10141
8333
|
</Item>
|
|
10142
|
-
<Item class="ModuleScript" referent="
|
|
8334
|
+
<Item class="ModuleScript" referent="25">
|
|
10143
8335
|
<Properties>
|
|
10144
8336
|
<string name="Name">LuauExec</string>
|
|
10145
8337
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -10573,7 +8765,7 @@ return {
|
|
|
10573
8765
|
]]></string>
|
|
10574
8766
|
</Properties>
|
|
10575
8767
|
</Item>
|
|
10576
|
-
<Item class="ModuleScript" referent="
|
|
8768
|
+
<Item class="ModuleScript" referent="26">
|
|
10577
8769
|
<Properties>
|
|
10578
8770
|
<string name="Name">Recording</string>
|
|
10579
8771
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -10603,7 +8795,7 @@ return {
|
|
|
10603
8795
|
]]></string>
|
|
10604
8796
|
</Properties>
|
|
10605
8797
|
</Item>
|
|
10606
|
-
<Item class="ModuleScript" referent="
|
|
8798
|
+
<Item class="ModuleScript" referent="27">
|
|
10607
8799
|
<Properties>
|
|
10608
8800
|
<string name="Name">RenderMonitor</string>
|
|
10609
8801
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -10671,7 +8863,7 @@ return {
|
|
|
10671
8863
|
]]></string>
|
|
10672
8864
|
</Properties>
|
|
10673
8865
|
</Item>
|
|
10674
|
-
<Item class="ModuleScript" referent="
|
|
8866
|
+
<Item class="ModuleScript" referent="28">
|
|
10675
8867
|
<Properties>
|
|
10676
8868
|
<string name="Name">RuntimeLogBuffer</string>
|
|
10677
8869
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -10926,7 +9118,7 @@ return {
|
|
|
10926
9118
|
]]></string>
|
|
10927
9119
|
</Properties>
|
|
10928
9120
|
</Item>
|
|
10929
|
-
<Item class="ModuleScript" referent="
|
|
9121
|
+
<Item class="ModuleScript" referent="29">
|
|
10930
9122
|
<Properties>
|
|
10931
9123
|
<string name="Name">ServerUrlSettings</string>
|
|
10932
9124
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -11076,11 +9268,11 @@ return {
|
|
|
11076
9268
|
]]></string>
|
|
11077
9269
|
</Properties>
|
|
11078
9270
|
</Item>
|
|
11079
|
-
<Item class="ModuleScript" referent="
|
|
9271
|
+
<Item class="ModuleScript" referent="30">
|
|
11080
9272
|
<Properties>
|
|
11081
9273
|
<string name="Name">State</string>
|
|
11082
9274
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
11083
|
-
local CURRENT_VERSION = "
|
|
9275
|
+
local CURRENT_VERSION = "3.0.0"
|
|
11084
9276
|
local PLUGIN_VARIANT = "inspector"
|
|
11085
9277
|
local BASE_PORT = 58741
|
|
11086
9278
|
local function createConnection(port)
|
|
@@ -11116,7 +9308,7 @@ return {
|
|
|
11116
9308
|
]]></string>
|
|
11117
9309
|
</Properties>
|
|
11118
9310
|
</Item>
|
|
11119
|
-
<Item class="ModuleScript" referent="
|
|
9311
|
+
<Item class="ModuleScript" referent="31">
|
|
11120
9312
|
<Properties>
|
|
11121
9313
|
<string name="Name">StopPlayMonitor</string>
|
|
11122
9314
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -11414,7 +9606,7 @@ return {
|
|
|
11414
9606
|
]]></string>
|
|
11415
9607
|
</Properties>
|
|
11416
9608
|
</Item>
|
|
11417
|
-
<Item class="ModuleScript" referent="
|
|
9609
|
+
<Item class="ModuleScript" referent="32">
|
|
11418
9610
|
<Properties>
|
|
11419
9611
|
<string name="Name">UI</string>
|
|
11420
9612
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -11966,7 +10158,7 @@ return {
|
|
|
11966
10158
|
]]></string>
|
|
11967
10159
|
</Properties>
|
|
11968
10160
|
</Item>
|
|
11969
|
-
<Item class="ModuleScript" referent="
|
|
10161
|
+
<Item class="ModuleScript" referent="33">
|
|
11970
10162
|
<Properties>
|
|
11971
10163
|
<string name="Name">Utils</string>
|
|
11972
10164
|
<string name="Source"><![CDATA[-- Compiled with roblox-ts v3.0.0
|
|
@@ -12286,11 +10478,62 @@ local function readScriptSource(instance)
|
|
|
12286
10478
|
end
|
|
12287
10479
|
return nil
|
|
12288
10480
|
end)
|
|
12289
|
-
|
|
12290
|
-
if _value ~= "" and _value then
|
|
10481
|
+
if ok and result ~= nil then
|
|
12291
10482
|
return result
|
|
12292
10483
|
end
|
|
12293
|
-
|
|
10484
|
+
-- @rbxts/types does not expose PluginSecurity Source reads.
|
|
10485
|
+
local readableScript = instance
|
|
10486
|
+
return readableScript.Source
|
|
10487
|
+
end
|
|
10488
|
+
--[[
|
|
10489
|
+
*
|
|
10490
|
+
* Writes newSource to instance and verifies the live editor text before
|
|
10491
|
+
* reporting success. expectedSource turns line-based edits into a
|
|
10492
|
+
* compare-and-set operation: if the document changes while
|
|
10493
|
+
* UpdateSourceAsync yields or before the direct fallback runs, the write is
|
|
10494
|
+
* rejected instead of overwriting the newer draft.
|
|
10495
|
+
|
|
10496
|
+
]]
|
|
10497
|
+
local function applyScriptSource(instance, newSource, expectedSource)
|
|
10498
|
+
local updateSuccess, updateResult = pcall(function()
|
|
10499
|
+
ScriptEditorService:UpdateSourceAsync(instance, function(currentSource)
|
|
10500
|
+
if expectedSource ~= nil and currentSource ~= expectedSource then
|
|
10501
|
+
error("Script source changed while the edit was being applied; read the script again and retry")
|
|
10502
|
+
end
|
|
10503
|
+
return newSource
|
|
10504
|
+
end)
|
|
10505
|
+
if readScriptSource(instance) ~= newSource then
|
|
10506
|
+
error("UpdateSourceAsync completed without updating the live script source")
|
|
10507
|
+
end
|
|
10508
|
+
end)
|
|
10509
|
+
if updateSuccess then
|
|
10510
|
+
return {
|
|
10511
|
+
success = true,
|
|
10512
|
+
method = "UpdateSourceAsync",
|
|
10513
|
+
}
|
|
10514
|
+
end
|
|
10515
|
+
local directSuccess, directResult = pcall(function()
|
|
10516
|
+
if expectedSource ~= nil and readScriptSource(instance) ~= expectedSource then
|
|
10517
|
+
error("Script source changed before direct assignment; read the script again and retry")
|
|
10518
|
+
end
|
|
10519
|
+
-- @rbxts/types does not expose PluginSecurity Source writes.
|
|
10520
|
+
local writableScript = instance
|
|
10521
|
+
writableScript.Source = newSource
|
|
10522
|
+
if readScriptSource(instance) ~= newSource then
|
|
10523
|
+
error("Direct assignment completed without updating the live script source")
|
|
10524
|
+
end
|
|
10525
|
+
end)
|
|
10526
|
+
if directSuccess then
|
|
10527
|
+
return {
|
|
10528
|
+
success = true,
|
|
10529
|
+
method = "direct",
|
|
10530
|
+
}
|
|
10531
|
+
end
|
|
10532
|
+
return {
|
|
10533
|
+
success = false,
|
|
10534
|
+
method = "direct",
|
|
10535
|
+
error = `UpdateSourceAsync failed: {updateResult}. Direct assignment failed: {directResult}`,
|
|
10536
|
+
}
|
|
12294
10537
|
end
|
|
12295
10538
|
local function convertPropertyValue(instance, propertyName, propertyValue)
|
|
12296
10539
|
if propertyValue == nil then
|
|
@@ -12751,6 +10994,7 @@ return {
|
|
|
12751
10994
|
splitLines = splitLines,
|
|
12752
10995
|
joinLines = joinLines,
|
|
12753
10996
|
readScriptSource = readScriptSource,
|
|
10997
|
+
applyScriptSource = applyScriptSource,
|
|
12754
10998
|
convertPropertyValue = convertPropertyValue,
|
|
12755
10999
|
evaluateFormula = evaluateFormula,
|
|
12756
11000
|
compareVersions = compareVersions,
|
|
@@ -12759,11 +11003,11 @@ return {
|
|
|
12759
11003
|
</Properties>
|
|
12760
11004
|
</Item>
|
|
12761
11005
|
</Item>
|
|
12762
|
-
<Item class="Folder" referent="
|
|
11006
|
+
<Item class="Folder" referent="38">
|
|
12763
11007
|
<Properties>
|
|
12764
11008
|
<string name="Name">include</string>
|
|
12765
11009
|
</Properties>
|
|
12766
|
-
<Item class="ModuleScript" referent="
|
|
11010
|
+
<Item class="ModuleScript" referent="34">
|
|
12767
11011
|
<Properties>
|
|
12768
11012
|
<string name="Name">LibMP</string>
|
|
12769
11013
|
<string name="Source"><![CDATA[-- =============================================================================
|
|
@@ -169147,7 +167391,7 @@ return LibMP
|
|
|
169147
167391
|
]]></string>
|
|
169148
167392
|
</Properties>
|
|
169149
167393
|
</Item>
|
|
169150
|
-
<Item class="ModuleScript" referent="
|
|
167394
|
+
<Item class="ModuleScript" referent="35">
|
|
169151
167395
|
<Properties>
|
|
169152
167396
|
<string name="Name">Promise</string>
|
|
169153
167397
|
<string name="Source"><![CDATA[--[[
|
|
@@ -171221,7 +169465,7 @@ return Promise
|
|
|
171221
169465
|
]]></string>
|
|
171222
169466
|
</Properties>
|
|
171223
169467
|
</Item>
|
|
171224
|
-
<Item class="ModuleScript" referent="
|
|
169468
|
+
<Item class="ModuleScript" referent="36">
|
|
171225
169469
|
<Properties>
|
|
171226
169470
|
<string name="Name">RuntimeLib</string>
|
|
171227
169471
|
<string name="Source"><![CDATA[local Promise = require(script.Parent.Promise)
|
|
@@ -171488,15 +169732,15 @@ return TS
|
|
|
171488
169732
|
</Properties>
|
|
171489
169733
|
</Item>
|
|
171490
169734
|
</Item>
|
|
171491
|
-
<Item class="Folder" referent="
|
|
169735
|
+
<Item class="Folder" referent="39">
|
|
171492
169736
|
<Properties>
|
|
171493
169737
|
<string name="Name">node_modules</string>
|
|
171494
169738
|
</Properties>
|
|
171495
|
-
<Item class="Folder" referent="
|
|
169739
|
+
<Item class="Folder" referent="40">
|
|
171496
169740
|
<Properties>
|
|
171497
169741
|
<string name="Name">@rbxts</string>
|
|
171498
169742
|
</Properties>
|
|
171499
|
-
<Item class="ModuleScript" referent="
|
|
169743
|
+
<Item class="ModuleScript" referent="37">
|
|
171500
169744
|
<Properties>
|
|
171501
169745
|
<string name="Name">services</string>
|
|
171502
169746
|
<string name="Source"><![CDATA[return setmetatable({}, {
|