ue-mcp 1.2.4 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/action-class.js +56 -3
- package/dist/action-class.js.map +1 -1
- package/dist/bridge-timeouts.d.ts +64 -0
- package/dist/bridge-timeouts.js +118 -0
- package/dist/bridge-timeouts.js.map +1 -0
- package/dist/bridge.js +10 -2
- package/dist/bridge.js.map +1 -1
- package/dist/editor-control.d.ts +72 -5
- package/dist/editor-control.js +164 -140
- package/dist/editor-control.js.map +1 -1
- package/dist/editor-target.d.ts +55 -1
- package/dist/editor-target.js +107 -10
- package/dist/editor-target.js.map +1 -1
- package/dist/engine-observer.d.ts +59 -5
- package/dist/engine-observer.js +249 -29
- package/dist/engine-observer.js.map +1 -1
- package/dist/engine-root.d.ts +91 -0
- package/dist/engine-root.js +448 -0
- package/dist/engine-root.js.map +1 -0
- package/dist/epic-enrich.js +16 -1
- package/dist/epic-enrich.js.map +1 -1
- package/dist/feedback-cli.js +4 -0
- package/dist/feedback-cli.js.map +1 -1
- package/dist/feedback-deferred.d.ts +9 -0
- package/dist/feedback-deferred.js +2 -0
- package/dist/feedback-deferred.js.map +1 -1
- package/dist/feedback-fallback.d.ts +99 -0
- package/dist/feedback-fallback.js +173 -0
- package/dist/feedback-fallback.js.map +1 -0
- package/dist/flow/write-methods.js +20 -0
- package/dist/flow/write-methods.js.map +1 -1
- package/dist/lean-context.js +8 -3
- package/dist/lean-context.js.map +1 -1
- package/dist/locking.js +11 -2
- package/dist/locking.js.map +1 -1
- package/dist/project.d.ts +11 -0
- package/dist/project.js +23 -2
- package/dist/project.js.map +1 -1
- package/dist/python-gate.d.ts +95 -0
- package/dist/python-gate.js +175 -0
- package/dist/python-gate.js.map +1 -0
- package/dist/tool-counts.json +16 -16
- package/dist/tools/animation.js +288 -24
- package/dist/tools/animation.js.map +1 -1
- package/dist/tools/asset.js +79 -14
- package/dist/tools/asset.js.map +1 -1
- package/dist/tools/audio.js +59 -5
- package/dist/tools/audio.js.map +1 -1
- package/dist/tools/blueprint.js +29 -12
- package/dist/tools/blueprint.js.map +1 -1
- package/dist/tools/chooser.js +4 -1
- package/dist/tools/chooser.js.map +1 -1
- package/dist/tools/editor.js +81 -43
- package/dist/tools/editor.js.map +1 -1
- package/dist/tools/feedback.js +214 -48
- package/dist/tools/feedback.js.map +1 -1
- package/dist/tools/foliage.js +27 -1
- package/dist/tools/foliage.js.map +1 -1
- package/dist/tools/gameplay.js +38 -11
- package/dist/tools/gameplay.js.map +1 -1
- package/dist/tools/gas.js +17 -5
- package/dist/tools/gas.js.map +1 -1
- package/dist/tools/landscape.js +22 -7
- package/dist/tools/landscape.js.map +1 -1
- package/dist/tools/level.js +322 -51
- package/dist/tools/level.js.map +1 -1
- package/dist/tools/material.js +10 -4
- package/dist/tools/material.js.map +1 -1
- package/dist/tools/niagara.js +3 -2
- package/dist/tools/niagara.js.map +1 -1
- package/dist/tools/pcg.js +6 -5
- package/dist/tools/pcg.js.map +1 -1
- package/dist/tools/project.js +47 -20
- package/dist/tools/project.js.map +1 -1
- package/dist/types.d.ts +21 -0
- package/dist/types.js +46 -3
- package/dist/types.js.map +1 -1
- package/dist/ue-mcp.default.yml +493 -125
- package/package.json +2 -2
- package/plugin/ue_mcp_bridge/NATIVE_RUNTIME_VISIBILITY.md +53 -0
- package/plugin/ue_mcp_bridge/NATIVE_STATIC_MESH_USAGE_PROGRESS.md +115 -0
- package/plugin/ue_mcp_bridge/README_MassHandlers.md +97 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +14 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +21 -4
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +9 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerJsonProperty.h +395 -69
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +79 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +25 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +3 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRigSequencer.cpp +3061 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRetargeterAuthoring.cpp +961 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRigAuthoring.cpp +900 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Pose.cpp +769 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Sequence.cpp +44 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_SkeletalLive.cpp +217 -11
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_StateMachine.cpp +551 -24
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Validation.cpp +735 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +352 -73
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +8 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkProperties.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.cpp +503 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.h +21 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkUpsert.cpp +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Enum.cpp +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.cpp +902 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.h +33 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Import.cpp +478 -134
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Mesh.cpp +5 -5
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.cpp +933 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.h +35 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Redirectors.cpp +478 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_RenderTarget.cpp +1 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Sockets.cpp +4 -4
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +2 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Subobject.cpp +319 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_SoundCue.cpp +3 -3
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +482 -35
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +10 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.cpp +502 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.h +43 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Functions.cpp +89 -7
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Graph.cpp +17 -51
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +107 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Properties.cpp +10 -10
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Search.cpp +648 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +5 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.cpp +252 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.h +10 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +252 -41
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +4 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +250 -27
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIE.cpp +303 -125
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIERuntime.cpp +73 -50
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_RuntimeVisibility.cpp +757 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.cpp +11 -2
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +3 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers_Batch.cpp +419 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +39 -161
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +66 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BTAuthoring.cpp +1323 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BehaviorTree.cpp +1211 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +2 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +60 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers_Runtime.cpp +363 -12
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/HandlerEditorState.h +84 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +1288 -36
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +3 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +41 -16
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +959 -213
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h +66 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_BatchWrite.cpp +1571 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Convert.cpp +316 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Inspection.cpp +280 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection.cpp +666 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection_Internal.h +63 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Lights.cpp +43 -12
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_MultiLevel.cpp +13 -47
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_PostProcess.cpp +527 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Query.cpp +1169 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Refresh.cpp +723 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Save.cpp +325 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Spatial.cpp +360 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Trace.cpp +178 -58
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Transient.cpp +337 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Volumes.cpp +25 -12
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartition.cpp +10 -9
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartitionSettings.cpp +686 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.cpp +467 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.h +22 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +452 -175
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +5 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Build.cpp +597 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +17 -15
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +38 -168
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +39 -30
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +392 -78
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +2 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers_Internal.h +83 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.cpp +200 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.h +15 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +19 -12
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/StateTreeHandlers.cpp +31 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +307 -69
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +84 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Extraction.cpp +8 -41
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Properties.cpp +33 -52
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/ActorSelectorTests.cpp +344 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationControlRigTimelineTests.cpp +60 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationPoseTests.cpp +115 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetBulkReadTests.cpp +177 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetDeleteGuardTests.cpp +276 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPathResolutionTests.cpp +243 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPropertyPersistTests.cpp +213 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetSubobjectTests.cpp +235 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AutomationRunnerTests.cpp +72 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeAuthoringTests.cpp +526 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeNodeTests.cpp +334 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BlueprintHandlerSurfaceTests.cpp +362 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BridgeProtocolTests.cpp +14 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/CollisionQueryTests.cpp +288 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/DataTableRowWriteTests.cpp +453 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/EditorFunctionCallTests.cpp +223 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/FoliageBatchTests.cpp +147 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GameThreadGateTests.cpp +82 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GasLiveAttributeTests.cpp +183 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LandscapeSampleTests.cpp +119 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelBatchWriteTests.cpp +176 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelComponentTreeInstanceCountTests.cpp +189 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelConvertBrushesTests.cpp +100 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelInstanceProjectionTests.cpp +265 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelPostProcessOverrideTests.cpp +258 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelQueryComponentsTests.cpp +195 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelRefreshTests.cpp +142 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelSaveReportTests.cpp +125 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelScriptHandlersTests.cpp +42 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelStaticMeshUsageTests.cpp +412 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTraceWorldScopeTests.cpp +133 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTransientActorTests.cpp +205 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelWorldPartitionSettingsTests.cpp +168 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTestTypes.h +51 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTests.cpp +379 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MaterialBuildTests.cpp +238 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshBooleanTests.cpp +170 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshGeometryTests.cpp +116 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageSaveExtensionTests.cpp +161 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageWriteGuardTests.cpp +253 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/RuntimeVisibilityTests.cpp +143 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerHandlerTests.cpp +660 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerScrubTests.cpp +50 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SkeletonDiffTests.cpp +685 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/WidgetBlueprintResolveTests.cpp +145 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +80 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerFunctionCall.h +509 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerQuery.h +407 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerUtils.h +1008 -77
- package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +87 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/MCPEngineStatus.cpp +152 -14
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/Tests/MCPEngineStatusTests.cpp +65 -0
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Public/MCPEngineStatus.h +32 -1
- package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/UE_MCP_BridgeStatus.Build.cs +2 -0
- package/skills/ue-mcp-animation/SKILL.md +154 -0
- package/skills/ue-mcp-blueprint/SKILL.md +71 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
#if WITH_DEV_AUTOMATION_TESTS
|
|
2
|
+
|
|
3
|
+
#include "Handlers/GameplayHandlers.h"
|
|
4
|
+
#include "HandlerRegistry.h"
|
|
5
|
+
#include "Misc/AutomationTest.h"
|
|
6
|
+
|
|
7
|
+
#include "Dom/JsonObject.h"
|
|
8
|
+
#include "Dom/JsonValue.h"
|
|
9
|
+
#include "UObject/Package.h"
|
|
10
|
+
#include "UObject/UObjectGlobals.h"
|
|
11
|
+
|
|
12
|
+
#include "BehaviorTree/BlackboardData.h"
|
|
13
|
+
#include "BehaviorTree/Blackboard/BlackboardKeyType.h"
|
|
14
|
+
#include "BehaviorTree/BTNode.h"
|
|
15
|
+
|
|
16
|
+
namespace
|
|
17
|
+
{
|
|
18
|
+
// The BT node classes under test are resolved by path rather than included
|
|
19
|
+
// by header, so a build without one of them skips the case instead of
|
|
20
|
+
// failing to link.
|
|
21
|
+
UClass* MCPBTTestFindClass(const TCHAR* ClassPath)
|
|
22
|
+
{
|
|
23
|
+
return FindObject<UClass>(nullptr, ClassPath);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
UBTNode* MCPBTTestMakeNode(const TCHAR* ClassPath)
|
|
27
|
+
{
|
|
28
|
+
UClass* Class = MCPBTTestFindClass(ClassPath);
|
|
29
|
+
if (!Class) return nullptr;
|
|
30
|
+
return NewObject<UBTNode>(GetTransientPackage(), Class);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
FString MCPBTTestGetString(const TSharedPtr<FJsonObject>& Object, const TCHAR* Field)
|
|
34
|
+
{
|
|
35
|
+
FString Value;
|
|
36
|
+
if (Object.IsValid()) Object->TryGetStringField(Field, Value);
|
|
37
|
+
return Value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// #887: get_behavior_tree_info walked UBlackboardData::Keys as if it were an
|
|
42
|
+
// array of UObject pointers. It is an array of FBlackboardEntry structs, so the
|
|
43
|
+
// walk read each entry's FName as a pointer and dereferenced it, and every
|
|
44
|
+
// blackboard with at least one key took the editor down with an access
|
|
45
|
+
// violation. This test builds that exact shape in memory.
|
|
46
|
+
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
|
47
|
+
FMCPBehaviorTreeBlackboardKeysTest,
|
|
48
|
+
"UE.MCP.Gameplay.BehaviorTree.BlackboardKeys",
|
|
49
|
+
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
|
|
50
|
+
|
|
51
|
+
bool FMCPBehaviorTreeBlackboardKeysTest::RunTest(const FString& Parameters)
|
|
52
|
+
{
|
|
53
|
+
UBlackboardData* Blackboard = NewObject<UBlackboardData>(GetTransientPackage());
|
|
54
|
+
TestNotNull(TEXT("blackboard was created"), Blackboard);
|
|
55
|
+
if (!Blackboard) return false;
|
|
56
|
+
|
|
57
|
+
UClass* ObjectKeyClass = MCPBTTestFindClass(TEXT("/Script/AIModule.BlackboardKeyType_Object"));
|
|
58
|
+
|
|
59
|
+
FBlackboardEntry Typed;
|
|
60
|
+
Typed.EntryName = TEXT("TargetActor");
|
|
61
|
+
if (ObjectKeyClass)
|
|
62
|
+
{
|
|
63
|
+
Typed.KeyType = NewObject<UBlackboardKeyType>(Blackboard, ObjectKeyClass);
|
|
64
|
+
}
|
|
65
|
+
Blackboard->Keys.Add(Typed);
|
|
66
|
+
|
|
67
|
+
// A key whose type was never picked is a real authoring state, and the
|
|
68
|
+
// reader has to describe it rather than dereference it.
|
|
69
|
+
FBlackboardEntry Untyped;
|
|
70
|
+
Untyped.EntryName = TEXT("PatrolIndex");
|
|
71
|
+
Blackboard->Keys.Add(Untyped);
|
|
72
|
+
|
|
73
|
+
const TArray<TSharedPtr<FJsonValue>> Keys = FGameplayHandlers::DescribeBlackboardKeys(Blackboard);
|
|
74
|
+
TestEqual(TEXT("both keys are described"), Keys.Num(), 2);
|
|
75
|
+
if (Keys.Num() != 2) return false;
|
|
76
|
+
|
|
77
|
+
const TSharedPtr<FJsonObject> First = Keys[0]->AsObject();
|
|
78
|
+
const TSharedPtr<FJsonObject> Second = Keys[1]->AsObject();
|
|
79
|
+
TestEqual(TEXT("first key name"), MCPBTTestGetString(First, TEXT("name")), FString(TEXT("TargetActor")));
|
|
80
|
+
TestEqual(TEXT("second key name"), MCPBTTestGetString(Second, TEXT("name")), FString(TEXT("PatrolIndex")));
|
|
81
|
+
TestEqual(TEXT("untyped key reports an empty type instead of crashing"),
|
|
82
|
+
MCPBTTestGetString(Second, TEXT("type")), FString());
|
|
83
|
+
if (ObjectKeyClass)
|
|
84
|
+
{
|
|
85
|
+
TestEqual(TEXT("typed key reports its short type name"),
|
|
86
|
+
MCPBTTestGetString(First, TEXT("type")), FString(TEXT("Object")));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// A null blackboard is an empty answer, never a dereference.
|
|
90
|
+
TestEqual(TEXT("null blackboard yields no keys"),
|
|
91
|
+
FGameplayHandlers::DescribeBlackboardKeys(nullptr).Num(), 0);
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// #888: BTDecorator_Blackboard keeps its whole configuration in protected C++
|
|
96
|
+
// fields, so the graph read used to report class and name only. Every field a
|
|
97
|
+
// "the tree runs but the wrong branch fires" investigation needs comes back now.
|
|
98
|
+
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
|
99
|
+
FMCPBehaviorTreeDecoratorConfigTest,
|
|
100
|
+
"UE.MCP.Gameplay.BehaviorTree.DecoratorConfig",
|
|
101
|
+
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
|
|
102
|
+
|
|
103
|
+
bool FMCPBehaviorTreeDecoratorConfigTest::RunTest(const FString& Parameters)
|
|
104
|
+
{
|
|
105
|
+
UBTNode* Decorator = MCPBTTestMakeNode(TEXT("/Script/AIModule.BTDecorator_Blackboard"));
|
|
106
|
+
if (!Decorator)
|
|
107
|
+
{
|
|
108
|
+
AddInfo(TEXT("BTDecorator_Blackboard is not present in this build; skipping."));
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// The nested write is the #919 path: a dotted address into a protected
|
|
113
|
+
// struct field on an owned node subobject.
|
|
114
|
+
FString Error;
|
|
115
|
+
TestTrue(TEXT("selected blackboard key is writable through a dotted path"),
|
|
116
|
+
FGameplayHandlers::WriteBTNodeProperty(Decorator, TEXT("BlackboardKey.SelectedKeyName"),
|
|
117
|
+
MakeShared<FJsonValueString>(TEXT("TargetActor")), Error));
|
|
118
|
+
TestEqual(TEXT("no error writing the selected key"), Error, FString());
|
|
119
|
+
|
|
120
|
+
#if WITH_EDITORONLY_DATA
|
|
121
|
+
// The comparison operation is authored data, so the engine declares it
|
|
122
|
+
// editor-only. It is the field that says whether the branch tests for
|
|
123
|
+
// "is set" or "is not set".
|
|
124
|
+
TestTrue(TEXT("basic operation is writable by enumerator name"),
|
|
125
|
+
FGameplayHandlers::WriteBTNodeProperty(Decorator, TEXT("BasicOperation"),
|
|
126
|
+
MakeShared<FJsonValueString>(TEXT("NotSet")), Error));
|
|
127
|
+
#endif
|
|
128
|
+
TestTrue(TEXT("flow abort mode is writable by enumerator name"),
|
|
129
|
+
FGameplayHandlers::WriteBTNodeProperty(Decorator, TEXT("FlowAbortMode"),
|
|
130
|
+
MakeShared<FJsonValueString>(TEXT("LowerPriority")), Error));
|
|
131
|
+
TestTrue(TEXT("notify observer is writable by enumerator name"),
|
|
132
|
+
FGameplayHandlers::WriteBTNodeProperty(Decorator, TEXT("NotifyObserver"),
|
|
133
|
+
MakeShared<FJsonValueString>(TEXT("ResultChange")), Error));
|
|
134
|
+
|
|
135
|
+
const TSharedPtr<FJsonObject> Described = FGameplayHandlers::DescribeBTNode(
|
|
136
|
+
Decorator, TEXT("Root.Children[0].Decorators[0]"), TEXT("Root.Children[0]"),
|
|
137
|
+
/*bIncludeProperties*/ false, /*bIncludeInherited*/ false, TSet<FString>());
|
|
138
|
+
|
|
139
|
+
TestEqual(TEXT("kind"), MCPBTTestGetString(Described, TEXT("kind")), FString(TEXT("decorator")));
|
|
140
|
+
TestEqual(TEXT("path"), MCPBTTestGetString(Described, TEXT("path")), FString(TEXT("Root.Children[0].Decorators[0]")));
|
|
141
|
+
TestEqual(TEXT("parentPath"), MCPBTTestGetString(Described, TEXT("parentPath")), FString(TEXT("Root.Children[0]")));
|
|
142
|
+
TestEqual(TEXT("class"), MCPBTTestGetString(Described, TEXT("class")), FString(TEXT("BTDecorator_Blackboard")));
|
|
143
|
+
TestTrue(TEXT("inverseCondition is reported"), Described->HasField(TEXT("inverseCondition")));
|
|
144
|
+
TestEqual(TEXT("flowAbortMode"), MCPBTTestGetString(Described, TEXT("flowAbortMode")), FString(TEXT("LowerPriority")));
|
|
145
|
+
TestEqual(TEXT("notifyObserver"), MCPBTTestGetString(Described, TEXT("notifyObserver")), FString(TEXT("ResultChange")));
|
|
146
|
+
#if WITH_EDITORONLY_DATA
|
|
147
|
+
TestEqual(TEXT("basicOperation"), MCPBTTestGetString(Described, TEXT("basicOperation")), FString(TEXT("NotSet")));
|
|
148
|
+
#endif
|
|
149
|
+
|
|
150
|
+
const TSharedPtr<FJsonObject>* BlackboardKey = nullptr;
|
|
151
|
+
TestTrue(TEXT("blackboardKey is reported"), Described->TryGetObjectField(TEXT("blackboardKey"), BlackboardKey));
|
|
152
|
+
if (BlackboardKey && (*BlackboardKey).IsValid())
|
|
153
|
+
{
|
|
154
|
+
TestEqual(TEXT("selectedKeyName"),
|
|
155
|
+
MCPBTTestGetString(*BlackboardKey, TEXT("selectedKeyName")), FString(TEXT("TargetActor")));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// A null node is answered, not dereferenced.
|
|
159
|
+
const TSharedPtr<FJsonObject> Empty = FGameplayHandlers::DescribeBTNode(
|
|
160
|
+
nullptr, TEXT("Root"), FString(), false, false, TSet<FString>());
|
|
161
|
+
TestTrue(TEXT("a null node yields an empty object"), Empty.IsValid() && Empty->Values.Num() == 0);
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// #940: on UE 5.8 BTTask_MoveTo::FilterClass is a FValueOrBBKey_Class, so the
|
|
166
|
+
// class lives in DefaultValue and get_editor_property reads the field as empty.
|
|
167
|
+
// #889 is the same struct shape one field over: AcceptableRadius is a
|
|
168
|
+
// FValueOrBBKey_Float, so the number a caller sends has to reach DefaultValue
|
|
169
|
+
// rather than bounce off the struct's export-text importer.
|
|
170
|
+
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
|
171
|
+
FMCPBehaviorTreeMoveToFilterClassTest,
|
|
172
|
+
"UE.MCP.Gameplay.BehaviorTree.MoveToFilterClass",
|
|
173
|
+
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
|
|
174
|
+
|
|
175
|
+
bool FMCPBehaviorTreeMoveToFilterClassTest::RunTest(const FString& Parameters)
|
|
176
|
+
{
|
|
177
|
+
UBTNode* MoveTo = MCPBTTestMakeNode(TEXT("/Script/AIModule.BTTask_MoveTo"));
|
|
178
|
+
if (!MoveTo)
|
|
179
|
+
{
|
|
180
|
+
AddInfo(TEXT("BTTask_MoveTo is not present in this build; skipping."));
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
FString Error;
|
|
185
|
+
|
|
186
|
+
// A JSON number aimed at the struct lands on its DefaultValue.
|
|
187
|
+
TestTrue(TEXT("AcceptableRadius accepts a bare JSON number"),
|
|
188
|
+
FGameplayHandlers::WriteBTNodeProperty(MoveTo, TEXT("AcceptableRadius"),
|
|
189
|
+
MakeShared<FJsonValueNumber>(60.0), Error));
|
|
190
|
+
TestEqual(TEXT("no error writing AcceptableRadius"), Error, FString());
|
|
191
|
+
|
|
192
|
+
TSharedPtr<FJsonValue> Radius = FGameplayHandlers::ReadBTNodeProperty(MoveTo, TEXT("AcceptableRadius"), Error);
|
|
193
|
+
TestTrue(TEXT("AcceptableRadius reads back as an object"), Radius.IsValid() && Radius->Type == EJson::Object);
|
|
194
|
+
if (Radius.IsValid() && Radius->Type == EJson::Object)
|
|
195
|
+
{
|
|
196
|
+
double Stored = 0.0;
|
|
197
|
+
Radius->AsObject()->TryGetNumberField(TEXT("defaultValue"), Stored);
|
|
198
|
+
TestEqual(TEXT("AcceptableRadius DefaultValue"), Stored, 60.0);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// #919: the filtered property read names what it wants and gets that, with
|
|
202
|
+
// the FValueOrBBKey_* struct already unpacked.
|
|
203
|
+
TSet<FString> Filter;
|
|
204
|
+
Filter.Add(TEXT("acceptableradius"));
|
|
205
|
+
const TSharedPtr<FJsonObject> Filtered = FGameplayHandlers::DescribeBTNode(
|
|
206
|
+
MoveTo, TEXT("Root.Children[0]"), TEXT("Root"),
|
|
207
|
+
/*bIncludeProperties*/ true, /*bIncludeInherited*/ false, Filter);
|
|
208
|
+
const TSharedPtr<FJsonObject>* Properties = nullptr;
|
|
209
|
+
TestTrue(TEXT("a filtered read reports properties"), Filtered->TryGetObjectField(TEXT("properties"), Properties));
|
|
210
|
+
if (Properties && (*Properties).IsValid())
|
|
211
|
+
{
|
|
212
|
+
TestEqual(TEXT("only the named property is reported"), (*Properties)->Values.Num(), 1);
|
|
213
|
+
TestTrue(TEXT("the named property is the one asked for"), (*Properties)->HasField(TEXT("AcceptableRadius")));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// FilterClass is the same shape holding a class.
|
|
217
|
+
UClass* FilterClass = MCPBTTestFindClass(TEXT("/Script/NavigationSystem.RecastFilter_UseDefaultArea"));
|
|
218
|
+
if (!FilterClass)
|
|
219
|
+
{
|
|
220
|
+
AddInfo(TEXT("RecastFilter_UseDefaultArea is not present in this build; skipping the class half."));
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
const FString FilterClassPath = FilterClass->GetPathName();
|
|
224
|
+
|
|
225
|
+
TestTrue(TEXT("FilterClass accepts a class path"),
|
|
226
|
+
FGameplayHandlers::WriteBTNodeProperty(MoveTo, TEXT("FilterClass"),
|
|
227
|
+
MakeShared<FJsonValueString>(FilterClassPath), Error));
|
|
228
|
+
TestEqual(TEXT("no error writing FilterClass"), Error, FString());
|
|
229
|
+
|
|
230
|
+
TSharedPtr<FJsonValue> FilterValue = FGameplayHandlers::ReadBTNodeProperty(MoveTo, TEXT("FilterClass"), Error);
|
|
231
|
+
TestTrue(TEXT("FilterClass reads back as an object"), FilterValue.IsValid() && FilterValue->Type == EJson::Object);
|
|
232
|
+
if (FilterValue.IsValid() && FilterValue->Type == EJson::Object)
|
|
233
|
+
{
|
|
234
|
+
TestEqual(TEXT("FilterClass DefaultValue is the class that was written"),
|
|
235
|
+
MCPBTTestGetString(FilterValue->AsObject(), TEXT("defaultValue")), FilterClassPath);
|
|
236
|
+
bool bBound = true;
|
|
237
|
+
FilterValue->AsObject()->TryGetBoolField(TEXT("isBound"), bBound);
|
|
238
|
+
TestFalse(TEXT("a literal class is not a blackboard binding"), bBound);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// An object value writes the struct's own fields, which is how the field
|
|
242
|
+
// is bound to a blackboard key instead of pinned to a literal.
|
|
243
|
+
TSharedPtr<FJsonObject> Binding = MakeShared<FJsonObject>();
|
|
244
|
+
Binding->SetStringField(TEXT("Key"), TEXT("NavFilter"));
|
|
245
|
+
TestTrue(TEXT("FilterClass accepts a blackboard key binding"),
|
|
246
|
+
FGameplayHandlers::WriteBTNodeProperty(MoveTo, TEXT("FilterClass"),
|
|
247
|
+
MakeShared<FJsonValueObject>(Binding), Error));
|
|
248
|
+
|
|
249
|
+
FilterValue = FGameplayHandlers::ReadBTNodeProperty(MoveTo, TEXT("FilterClass"), Error);
|
|
250
|
+
if (FilterValue.IsValid() && FilterValue->Type == EJson::Object)
|
|
251
|
+
{
|
|
252
|
+
TestEqual(TEXT("bound key name"),
|
|
253
|
+
MCPBTTestGetString(FilterValue->AsObject(), TEXT("key")), FString(TEXT("NavFilter")));
|
|
254
|
+
bool bBound = false;
|
|
255
|
+
FilterValue->AsObject()->TryGetBoolField(TEXT("isBound"), bBound);
|
|
256
|
+
TestTrue(TEXT("a key name reads as bound"), bBound);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Null clears the class without touching the binding.
|
|
260
|
+
TestTrue(TEXT("FilterClass accepts null to clear the class"),
|
|
261
|
+
FGameplayHandlers::WriteBTNodeProperty(MoveTo, TEXT("FilterClass"),
|
|
262
|
+
MakeShared<FJsonValueNull>(), Error));
|
|
263
|
+
FilterValue = FGameplayHandlers::ReadBTNodeProperty(MoveTo, TEXT("FilterClass"), Error);
|
|
264
|
+
if (FilterValue.IsValid() && FilterValue->Type == EJson::Object)
|
|
265
|
+
{
|
|
266
|
+
TestEqual(TEXT("cleared DefaultValue"),
|
|
267
|
+
MCPBTTestGetString(FilterValue->AsObject(), TEXT("defaultValueName")), FString());
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// A property the node does not declare is a structured error, never a
|
|
271
|
+
// silent no-op and never a dereference.
|
|
272
|
+
TestFalse(TEXT("an unknown property is rejected"),
|
|
273
|
+
FGameplayHandlers::WriteBTNodeProperty(MoveTo, TEXT("NotAProperty"),
|
|
274
|
+
MakeShared<FJsonValueNumber>(1.0), Error));
|
|
275
|
+
TestTrue(TEXT("the rejection names the property"), Error.Contains(TEXT("NotAProperty")));
|
|
276
|
+
|
|
277
|
+
// A null node is answered, not dereferenced.
|
|
278
|
+
TestFalse(TEXT("a null node is rejected"),
|
|
279
|
+
FGameplayHandlers::WriteBTNodeProperty(nullptr, TEXT("AcceptableRadius"),
|
|
280
|
+
MakeShared<FJsonValueNumber>(1.0), Error));
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// The BT actions have to be reachable by the names the TypeScript schema
|
|
285
|
+
// advertises, and each has to answer a call with no parameters with a
|
|
286
|
+
// structured error rather than a crash.
|
|
287
|
+
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
|
|
288
|
+
FMCPBehaviorTreeRegistrationTest,
|
|
289
|
+
"UE.MCP.Gameplay.BehaviorTree.RegistrationAndPreflight",
|
|
290
|
+
EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)
|
|
291
|
+
|
|
292
|
+
bool FMCPBehaviorTreeRegistrationTest::RunTest(const FString& Parameters)
|
|
293
|
+
{
|
|
294
|
+
FMCPHandlerRegistry Registry;
|
|
295
|
+
FGameplayHandlers::RegisterHandlers(Registry);
|
|
296
|
+
|
|
297
|
+
const TCHAR* Methods[] = {
|
|
298
|
+
TEXT("get_behavior_tree_info"),
|
|
299
|
+
TEXT("read_behavior_tree_graph"),
|
|
300
|
+
TEXT("read_bt_node_properties"),
|
|
301
|
+
TEXT("list_bt_tasks"),
|
|
302
|
+
TEXT("set_bt_node_property"),
|
|
303
|
+
TEXT("set_bt_task_property"),
|
|
304
|
+
};
|
|
305
|
+
for (const TCHAR* Method : Methods)
|
|
306
|
+
{
|
|
307
|
+
TestTrue(FString::Printf(TEXT("%s is registered"), Method), Registry.HasHandler(Method));
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Every action that needs an asset path says so, and list_bt_tasks answers
|
|
311
|
+
// without one because a directory sweep is its whole point.
|
|
312
|
+
const TCHAR* NeedAssetPath[] = {
|
|
313
|
+
TEXT("get_behavior_tree_info"),
|
|
314
|
+
TEXT("read_behavior_tree_graph"),
|
|
315
|
+
TEXT("read_bt_node_properties"),
|
|
316
|
+
TEXT("set_bt_node_property"),
|
|
317
|
+
TEXT("set_bt_task_property"),
|
|
318
|
+
};
|
|
319
|
+
for (const TCHAR* Method : NeedAssetPath)
|
|
320
|
+
{
|
|
321
|
+
const TSharedPtr<FJsonValue> Response = Registry.ExecuteHandler(Method, MakeShared<FJsonObject>());
|
|
322
|
+
TestTrue(FString::Printf(TEXT("%s returns an object"), Method),
|
|
323
|
+
Response.IsValid() && Response->Type == EJson::Object);
|
|
324
|
+
if (!Response.IsValid() || Response->Type != EJson::Object) continue;
|
|
325
|
+
|
|
326
|
+
const TSharedPtr<FJsonObject> Object = Response->AsObject();
|
|
327
|
+
TestFalse(FString::Printf(TEXT("%s rejects an empty call"), Method), Object->GetBoolField(TEXT("success")));
|
|
328
|
+
TestTrue(FString::Printf(TEXT("%s names assetPath"), Method),
|
|
329
|
+
Object->GetStringField(TEXT("error")).Contains(TEXT("assetPath")));
|
|
330
|
+
}
|
|
331
|
+
return true;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
#endif
|