ue-mcp 1.2.3 → 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.
Files changed (255) hide show
  1. package/README.md +4 -3
  2. package/dist/action-class.js +56 -3
  3. package/dist/action-class.js.map +1 -1
  4. package/dist/bridge-timeouts.d.ts +64 -0
  5. package/dist/bridge-timeouts.js +118 -0
  6. package/dist/bridge-timeouts.js.map +1 -0
  7. package/dist/bridge.js +10 -2
  8. package/dist/bridge.js.map +1 -1
  9. package/dist/editor-control.d.ts +72 -5
  10. package/dist/editor-control.js +164 -140
  11. package/dist/editor-control.js.map +1 -1
  12. package/dist/editor-target.d.ts +55 -1
  13. package/dist/editor-target.js +107 -10
  14. package/dist/editor-target.js.map +1 -1
  15. package/dist/engine-observer.d.ts +59 -5
  16. package/dist/engine-observer.js +249 -29
  17. package/dist/engine-observer.js.map +1 -1
  18. package/dist/engine-root.d.ts +91 -0
  19. package/dist/engine-root.js +448 -0
  20. package/dist/engine-root.js.map +1 -0
  21. package/dist/epic-enrich.js +16 -1
  22. package/dist/epic-enrich.js.map +1 -1
  23. package/dist/feedback-cli.js +4 -0
  24. package/dist/feedback-cli.js.map +1 -1
  25. package/dist/feedback-deferred.d.ts +9 -0
  26. package/dist/feedback-deferred.js +2 -0
  27. package/dist/feedback-deferred.js.map +1 -1
  28. package/dist/feedback-fallback.d.ts +99 -0
  29. package/dist/feedback-fallback.js +173 -0
  30. package/dist/feedback-fallback.js.map +1 -0
  31. package/dist/flow/write-methods.js +20 -0
  32. package/dist/flow/write-methods.js.map +1 -1
  33. package/dist/index.js +41 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/lean-context.js +8 -3
  36. package/dist/lean-context.js.map +1 -1
  37. package/dist/locking.js +11 -2
  38. package/dist/locking.js.map +1 -1
  39. package/dist/plugin/loader.d.ts +4 -0
  40. package/dist/plugin/loader.js +22 -8
  41. package/dist/plugin/loader.js.map +1 -1
  42. package/dist/plugin/manifest.d.ts +72 -52
  43. package/dist/plugin/manifest.js +118 -21
  44. package/dist/plugin/manifest.js.map +1 -1
  45. package/dist/plugin-cli.js +16 -3
  46. package/dist/plugin-cli.js.map +1 -1
  47. package/dist/project.d.ts +11 -0
  48. package/dist/project.js +23 -2
  49. package/dist/project.js.map +1 -1
  50. package/dist/python-gate.d.ts +95 -0
  51. package/dist/python-gate.js +175 -0
  52. package/dist/python-gate.js.map +1 -0
  53. package/dist/tool-counts.json +16 -16
  54. package/dist/tools/animation.js +288 -24
  55. package/dist/tools/animation.js.map +1 -1
  56. package/dist/tools/asset.js +79 -14
  57. package/dist/tools/asset.js.map +1 -1
  58. package/dist/tools/audio.js +59 -5
  59. package/dist/tools/audio.js.map +1 -1
  60. package/dist/tools/blueprint.js +29 -12
  61. package/dist/tools/blueprint.js.map +1 -1
  62. package/dist/tools/chooser.js +4 -1
  63. package/dist/tools/chooser.js.map +1 -1
  64. package/dist/tools/editor.js +81 -43
  65. package/dist/tools/editor.js.map +1 -1
  66. package/dist/tools/feedback.js +214 -48
  67. package/dist/tools/feedback.js.map +1 -1
  68. package/dist/tools/foliage.js +27 -1
  69. package/dist/tools/foliage.js.map +1 -1
  70. package/dist/tools/gameplay.js +38 -11
  71. package/dist/tools/gameplay.js.map +1 -1
  72. package/dist/tools/gas.js +17 -5
  73. package/dist/tools/gas.js.map +1 -1
  74. package/dist/tools/landscape.js +22 -7
  75. package/dist/tools/landscape.js.map +1 -1
  76. package/dist/tools/level.js +322 -51
  77. package/dist/tools/level.js.map +1 -1
  78. package/dist/tools/material.js +10 -4
  79. package/dist/tools/material.js.map +1 -1
  80. package/dist/tools/niagara.js +3 -2
  81. package/dist/tools/niagara.js.map +1 -1
  82. package/dist/tools/pcg.js +6 -5
  83. package/dist/tools/pcg.js.map +1 -1
  84. package/dist/tools/plugins.js +2 -0
  85. package/dist/tools/plugins.js.map +1 -1
  86. package/dist/tools/project.js +47 -20
  87. package/dist/tools/project.js.map +1 -1
  88. package/dist/types.d.ts +24 -0
  89. package/dist/types.js +46 -3
  90. package/dist/types.js.map +1 -1
  91. package/dist/ue-mcp.default.yml +493 -125
  92. package/package.json +2 -2
  93. package/plugin/ue_mcp_bridge/NATIVE_RUNTIME_VISIBILITY.md +53 -0
  94. package/plugin/ue_mcp_bridge/NATIVE_STATIC_MESH_USAGE_PROGRESS.md +115 -0
  95. package/plugin/ue_mcp_bridge/README_MassHandlers.md +97 -0
  96. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +14 -0
  97. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +21 -4
  98. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +9 -0
  99. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerJsonProperty.h +395 -69
  100. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +79 -3
  101. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +25 -0
  102. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +3 -3
  103. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRigSequencer.cpp +3061 -0
  104. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRetargeterAuthoring.cpp +961 -0
  105. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_IKRigAuthoring.cpp +900 -0
  106. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Pose.cpp +769 -0
  107. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Sequence.cpp +44 -3
  108. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_SkeletalLive.cpp +217 -11
  109. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_StateMachine.cpp +551 -24
  110. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_Validation.cpp +735 -0
  111. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +352 -73
  112. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +8 -0
  113. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkProperties.cpp +1 -1
  114. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.cpp +503 -0
  115. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkRead.h +21 -0
  116. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_BulkUpsert.cpp +2 -2
  117. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Enum.cpp +2 -2
  118. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.cpp +902 -0
  119. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Geometry.h +33 -0
  120. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Import.cpp +478 -134
  121. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Mesh.cpp +5 -5
  122. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.cpp +933 -0
  123. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_MeshBoolean.h +35 -0
  124. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Redirectors.cpp +478 -0
  125. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_RenderTarget.cpp +1 -1
  126. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Sockets.cpp +4 -4
  127. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +2 -2
  128. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Subobject.cpp +319 -0
  129. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers_SoundCue.cpp +3 -3
  130. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +482 -35
  131. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +10 -0
  132. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.cpp +502 -0
  133. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Collision.h +43 -0
  134. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Functions.cpp +89 -7
  135. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Graph.cpp +17 -51
  136. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +107 -0
  137. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Properties.cpp +10 -10
  138. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Search.cpp +648 -0
  139. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +5 -1
  140. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.cpp +252 -1
  141. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DiffHandlers.h +10 -2
  142. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +252 -41
  143. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +4 -0
  144. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +250 -27
  145. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIE.cpp +303 -125
  146. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_PIERuntime.cpp +73 -50
  147. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_RuntimeVisibility.cpp +757 -0
  148. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.cpp +11 -2
  149. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +3 -0
  150. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers_Batch.cpp +419 -0
  151. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +39 -161
  152. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +66 -1
  153. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BTAuthoring.cpp +1323 -0
  154. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_BehaviorTree.cpp +1211 -0
  155. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +2 -0
  156. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +60 -0
  157. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers_Runtime.cpp +363 -12
  158. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/HandlerEditorState.h +84 -0
  159. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +1288 -36
  160. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +3 -0
  161. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +41 -16
  162. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +959 -213
  163. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h +66 -0
  164. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_BatchWrite.cpp +1571 -0
  165. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Convert.cpp +316 -0
  166. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Inspection.cpp +280 -0
  167. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection.cpp +666 -0
  168. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_InstanceProjection_Internal.h +63 -0
  169. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Lights.cpp +43 -12
  170. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_MultiLevel.cpp +13 -47
  171. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_PostProcess.cpp +527 -0
  172. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Query.cpp +1169 -0
  173. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Refresh.cpp +723 -0
  174. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Save.cpp +325 -0
  175. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Spatial.cpp +360 -0
  176. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Trace.cpp +178 -58
  177. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Transient.cpp +337 -0
  178. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Volumes.cpp +25 -12
  179. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartition.cpp +10 -9
  180. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_WorldPartitionSettings.cpp +686 -0
  181. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.cpp +467 -0
  182. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MassHandlers.h +22 -0
  183. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +452 -175
  184. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +5 -0
  185. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Build.cpp +597 -0
  186. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +17 -15
  187. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +38 -168
  188. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +39 -30
  189. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +392 -78
  190. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +2 -0
  191. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers_Internal.h +83 -0
  192. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.cpp +200 -0
  193. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SkeletalMeshHandlers.h +15 -0
  194. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +19 -12
  195. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/StateTreeHandlers.cpp +31 -1
  196. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +307 -69
  197. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +84 -0
  198. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Extraction.cpp +8 -41
  199. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers_Properties.cpp +33 -52
  200. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/ActorSelectorTests.cpp +344 -0
  201. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationControlRigTimelineTests.cpp +60 -0
  202. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AnimationPoseTests.cpp +115 -0
  203. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetBulkReadTests.cpp +177 -0
  204. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetDeleteGuardTests.cpp +276 -0
  205. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPathResolutionTests.cpp +243 -0
  206. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetPropertyPersistTests.cpp +213 -0
  207. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AssetSubobjectTests.cpp +235 -0
  208. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/AutomationRunnerTests.cpp +72 -0
  209. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeAuthoringTests.cpp +526 -0
  210. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BehaviorTreeNodeTests.cpp +334 -0
  211. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BlueprintHandlerSurfaceTests.cpp +362 -0
  212. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/BridgeProtocolTests.cpp +14 -0
  213. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/CollisionQueryTests.cpp +288 -0
  214. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/DataTableRowWriteTests.cpp +453 -0
  215. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/EditorFunctionCallTests.cpp +223 -0
  216. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/FoliageBatchTests.cpp +147 -0
  217. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GameThreadGateTests.cpp +82 -0
  218. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/GasLiveAttributeTests.cpp +183 -0
  219. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LandscapeSampleTests.cpp +119 -0
  220. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelBatchWriteTests.cpp +176 -0
  221. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelComponentTreeInstanceCountTests.cpp +189 -0
  222. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelConvertBrushesTests.cpp +100 -0
  223. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelInstanceProjectionTests.cpp +265 -0
  224. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelPostProcessOverrideTests.cpp +258 -0
  225. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelQueryComponentsTests.cpp +195 -0
  226. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelRefreshTests.cpp +142 -0
  227. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelSaveReportTests.cpp +125 -0
  228. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelScriptHandlersTests.cpp +42 -0
  229. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelStaticMeshUsageTests.cpp +412 -0
  230. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTraceWorldScopeTests.cpp +133 -0
  231. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelTransientActorTests.cpp +205 -0
  232. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/LevelWorldPartitionSettingsTests.cpp +168 -0
  233. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTestTypes.h +51 -0
  234. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MCPInstancedStructPathTests.cpp +379 -0
  235. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MaterialBuildTests.cpp +238 -0
  236. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshBooleanTests.cpp +170 -0
  237. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/MeshGeometryTests.cpp +116 -0
  238. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageSaveExtensionTests.cpp +161 -0
  239. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/PackageWriteGuardTests.cpp +253 -0
  240. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/RuntimeVisibilityTests.cpp +143 -0
  241. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerHandlerTests.cpp +660 -0
  242. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SequencerScrubTests.cpp +50 -0
  243. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/SkeletonDiffTests.cpp +685 -0
  244. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Tests/WidgetBlueprintResolveTests.cpp +145 -0
  245. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +80 -0
  246. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerFunctionCall.h +509 -0
  247. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerQuery.h +407 -0
  248. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/HandlerUtils.h +1008 -77
  249. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +87 -0
  250. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/MCPEngineStatus.cpp +152 -14
  251. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/Tests/MCPEngineStatusTests.cpp +65 -0
  252. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Public/MCPEngineStatus.h +32 -1
  253. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/UE_MCP_BridgeStatus.Build.cs +2 -0
  254. package/skills/ue-mcp-animation/SKILL.md +154 -0
  255. package/skills/ue-mcp-blueprint/SKILL.md +71 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ue-mcp",
3
- "version": "1.2.3",
4
- "description": "Unreal Engine MCP server - 24 tools, 783+ actions for AI-driven editor control",
3
+ "version": "1.3.0",
4
+ "description": "Unreal Engine MCP server - 24 tools, 845+ actions for AI-driven editor control",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "exports": {
@@ -0,0 +1,53 @@
1
+ # Native Runtime Visibility Batch
2
+
3
+ This plugin exposes two raw bridge handlers for bounded, reversible visibility
4
+ changes in a running Play In Editor (PIE) world:
5
+
6
+ - `set_runtime_visibility`
7
+ - `restore_runtime_visibility`
8
+
9
+ The handlers replace repeated Python actor/component enumeration and one-off
10
+ visibility calls with one native preflighted operation. They are intentionally
11
+ plugin-only in this change. Raw bridge clients can discover both names through
12
+ `get_bridge_capabilities.actions`; adding a typed MCP server action is separate
13
+ work outside this plugin-scoped change.
14
+
15
+ ## Set contract
16
+
17
+ `set_runtime_visibility` requires `hidden` and exactly one actor selector:
18
+ `actorLabels`, `actorPaths`, or `actorClass`. Optional `componentNames` and
19
+ `componentClasses` filters select scene components. Class names use the shared
20
+ UE-MCP class resolver, including C++ prefixes, script paths, and Blueprint class
21
+ paths.
22
+
23
+ Safety defaults and limits:
24
+
25
+ - `world` is fixed to `pie`; `pieInstance` selects a specific PIE context and
26
+ is required when more than one PIE world is active.
27
+ - `dryRun` defaults to `true`.
28
+ - `maxTargets` defaults to 64 and cannot exceed 256.
29
+ - Explicit actor and component filter arrays cannot exceed 64 entries.
30
+ - `all` is rejected.
31
+ - Selection, descendant expansion, and rollback state capture finish before any
32
+ visibility mutation.
33
+ - Component state uses `SetVisibility` and `SetHiddenInGame`; actor state uses
34
+ `SetActorHiddenInGame`.
35
+ - No editor visibility flag is changed and no package is saved or dirtied.
36
+
37
+ When a non-dry-run call changes state, the response includes a standard rollback
38
+ payload for `restore_runtime_visibility`. Its opaque token refers to a bounded
39
+ native snapshot containing weak world and object identities, including Unreal's
40
+ object serials. Restore fails closed after PIE restarts or if any target was
41
+ destroyed, and it preflights every target before applying changes. Tokens are
42
+ process-local and expire when their snapshot is pruned or the plugin unloads.
43
+
44
+ Actor hidden state may be authority-owned or replicated. Callers should select
45
+ the intended server or client `pieInstance`; later replication can supersede a
46
+ client-local actor visibility change.
47
+
48
+ ## Native validation boundary
49
+
50
+ The plugin Automation test verifies registration, raw capability discovery, and
51
+ safe parameter/class/world rejections without mutating a user's running editor.
52
+ Live apply, propagation, multi-PIE selection, and rollback behavior require the
53
+ dedicated UE-MCP smoke project so they can operate on disposable runtime actors.
@@ -0,0 +1,115 @@
1
+ # Native Static Mesh Usage Progress
2
+
3
+ Last updated: 2026-08-12
4
+
5
+ ## Status
6
+
7
+ | Field | Value |
8
+ | --- | --- |
9
+ | Overall | Source implementation committed; native validation pending; draft PR awaiting review |
10
+ | Pull request | [db-lyon/ue-mcp#903](https://github.com/db-lyon/ue-mcp/pull/903) |
11
+ | Branch | `codex/native-static-mesh-usage` |
12
+ | Base | `db-lyon/ue-mcp:main` at `849a194` |
13
+ | Scope | `plugin/ue_mcp_bridge` only |
14
+ | Handler | `summarize_static_mesh_usage` |
15
+ | Mutation policy | Read-only |
16
+
17
+ ## Goal
18
+
19
+ Provide a native replacement for the repetitive current-level workflow of
20
+ enumerating actors, reading each static mesh component, and aggregating mesh
21
+ properties through many bridge calls or an `execute_python` script. The raw
22
+ bridge handler performs the common inspection in one bounded game-thread request.
23
+ A typed server action is intentionally deferred because this change is limited
24
+ to the UE-MCP plugin folder.
25
+
26
+ ## Completed
27
+
28
+ - [x] Register `summarize_static_mesh_usage` with the level handler registry.
29
+ - [x] Support exact `editor` and `pie` world selection, including `pieInstance`.
30
+ - [x] Scan loaded actors and all owned `UStaticMeshComponent` subclasses.
31
+ - [x] Count actors, components, and placements separately.
32
+ - [x] Count a plain static mesh component as one placement.
33
+ - [x] Count ISMC and HISM placements with `GetInstanceCount()`.
34
+ - [x] Preserve zero-instance components in component totals without adding placements.
35
+ - [x] Report null-mesh components diagnostically.
36
+ - [x] Sort results by placement count descending, then mesh path ascending.
37
+ - [x] Bound returned mesh rows to 1 through 500.
38
+ - [x] Bound occurrence examples to 0 through 256 across the response.
39
+ - [x] Fail closed above 8,192 unique loaded meshes.
40
+ - [x] Report full-scan totals even when result rows are truncated.
41
+ - [x] Author plugin-local Automation coverage for registration, world validation,
42
+ aggregation, ordering, plain and ISMC placement semantics, null meshes, and bounds.
43
+ - [x] Complete independent static review against Unreal Engine 5.8 APIs.
44
+ - [x] Open a plugin-only draft pull request.
45
+
46
+ ## Validation
47
+
48
+ | Check | Result | Evidence |
49
+ | --- | --- | --- |
50
+ | Local engine-free unit suite | Passed | 83 files, 840 tests |
51
+ | Local TypeScript type check | Passed | `npx tsc --noEmit` |
52
+ | Local unity collision audit | Passed | `npm run audit:unity` |
53
+ | Local em dash audit | Passed | `npm run audit:em-dash` |
54
+ | GitHub engine-free CI | Passed | Workflow run `31600014333`: 83 files and 840 unit tests, plus 4 files and 32 multi-editor tests |
55
+ | UE 5.8 API/static review | Passed | No P0 or P1 findings |
56
+ | Native Unreal compilation | Not yet proven | Guarded local build stopped before compilation because protected engine outputs would have changed |
57
+ | Native Automation execution | Not yet run | Requires a prepared Unreal test engine or upstream CI lane that compiles the plugin |
58
+
59
+ The GitHub CI runner has no Unreal installation. Its successful build job
60
+ exercises the repository's Node and TypeScript checks; it does not replace
61
+ native Unreal compilation or execution of the new Automation tests. The
62
+ workflow's `publish` and `surface_counts` jobs were skipped, not failed.
63
+
64
+ ## Changed Files
65
+
66
+ - `Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp`
67
+ - `Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h`
68
+ - `Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers_Inspection.cpp`
69
+ - `Source/UE_MCP_Bridge/Private/Tests/LevelStaticMeshUsageTests.cpp`
70
+ - `Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs`
71
+ - `NATIVE_STATIC_MESH_USAGE_PROGRESS.md`
72
+
73
+ ## Current Contract
74
+
75
+ Example parameters:
76
+
77
+ ```json
78
+ {
79
+ "world": "editor",
80
+ "maxResults": 100,
81
+ "includeOccurrences": false,
82
+ "maxOccurrences": 32
83
+ }
84
+ ```
85
+
86
+ The result is explicitly `loadedOnly`. It summarizes the selected loaded world
87
+ and makes no claim about unloaded World Partition actors. It performs no asset
88
+ loads, saves, or mutations.
89
+
90
+ ## Remaining Work
91
+
92
+ - [ ] Compile the plugin in a prepared Unreal Engine test lane.
93
+ - [ ] Run `UE.MCP.Level.SummarizeStaticMeshUsage.*` Automation tests.
94
+ - [ ] Address any upstream review comments on PR #903. None exist as of the
95
+ last-updated date.
96
+ - [ ] Decide separately whether to expose a typed server action outside the
97
+ plugin folder. That is intentionally not part of this plugin-only change.
98
+ - [ ] Mark the PR ready for review after native validation or maintainer approval
99
+ of the documented validation boundary.
100
+
101
+ ## Update Rules
102
+
103
+ Keep this file current whenever implementation, validation, review state, or
104
+ scope changes:
105
+
106
+ 1. Update the date and overall status.
107
+ 2. Move finished items into `Completed` or check them in place.
108
+ 3. Record exact validation commands and outcomes without overstating coverage.
109
+ 4. Add newly discovered blockers or follow-up work under `Remaining Work`.
110
+ 5. Keep all project-specific context outside this plugin progress record.
111
+
112
+ ## History
113
+
114
+ - 2026-08-12: Native handler, focused tests, static review, engine-free validation,
115
+ and draft PR completed. Native Unreal compilation remains pending.
@@ -0,0 +1,97 @@
1
+ # Mass entity config handler
2
+
3
+ `ensure_mass_entity_config` creates or idempotently extends a
4
+ `UMassEntityConfigAsset` without requiring a hard Mass module dependency in
5
+ the bridge. The handler resolves the Mass classes at runtime, so the bridge
6
+ continues to load when Mass is not enabled.
7
+
8
+ `read_mass_entity_config` is the corresponding read-only audit operation. It
9
+ returns `assetPath`, `assetClass`, `traitCount`, an ordered `traitClasses`
10
+ array, and ordered `traits` records. Each record contains `index`, `classPath`,
11
+ `className`, and a `properties` object. Object and soft-object properties are
12
+ reported as object paths, so a StateTree assignment can be verified exactly.
13
+
14
+ `read_state_tree` returns `schemaClass` and `schemaPath` plus `subTrees`. Each state record
15
+ contains ordered `tasks`, `enterConditions`, and `transitions`; node records
16
+ include `structType`, `instanceProperties`, and `nodeProperties` (including
17
+ `bConsideredForCompletion`). Transition records include `trigger`,
18
+ `transitionType`, `targetStateId`, `targetStatePath`, `bDelayTransition`,
19
+ `delayDuration`, and `delayRandomVariance`. The response also includes exact
20
+ `editorBindings` records with source/target struct IDs and paths.
21
+
22
+ ## Skeletal mesh instancing build flag
23
+
24
+ `set_skeletal_mesh_optimize_for_instancing` edits only the requested skeletal
25
+ mesh asset's LOD build settings. Parameters are `assetPath`, required boolean
26
+ `enabled`, and either `lodIndex` (default `0`) or `allLods: true`. It validates
27
+ the mesh and LOD selection before mutation, is idempotent, calls `Modify()`
28
+ before changing settings, and saves only that mesh package. The response
29
+ contains `updated`, `saved`, `changedLods`, and ordered `lods[]` records with
30
+ `lodIndex`, `beforeOptimizeForInstancing`, `afterOptimizeForInstancing`, and
31
+ `changed`. Each record also includes complete `beforeBuildSettings` and
32
+ `afterBuildSettings` objects, including `bOptimizeForInstancing` and the
33
+ other UE 5.8 skeletal build flags.
34
+
35
+ `read_skeletal_mesh_build_settings` is the read-only counterpart. It accepts
36
+ the same LOD selection parameters and returns `assetPath`, `lodCount`, and
37
+ `lods[]` with the exact current `bOptimizeForInstancing` value and complete
38
+ `afterBuildSettings` object for each LOD.
39
+
40
+ Example:
41
+
42
+ ```json
43
+ {
44
+ "assetPath": "/Game/Mass/WorkerAI.WorkerAI",
45
+ "onConflict": "update",
46
+ "traits": [
47
+ {
48
+ "class": "/Script/MassAIBehavior.MassStateTreeTrait",
49
+ "properties": {
50
+ "StateTree": "/Game/Mass/WorkerAIStateTree.WorkerAIStateTree"
51
+ }
52
+ }
53
+ ]
54
+ }
55
+ ```
56
+
57
+ The MMO persistent-pawn validation config uses this exact four-trait list:
58
+
59
+ ```json
60
+ {
61
+ "assetPath": "/Game/MMOValidation/MassPersistentPawn/DA_MassPersistentPawnWorkerAI.DA_MassPersistentPawnWorkerAI",
62
+ "onConflict": "update",
63
+ "traits": [
64
+ { "class": "/Script/MMOHumanoidMassRuntime.MMOHumanoidMassEntityTrait" },
65
+ { "class": "/Script/MassNavMeshNavigation.MassNavMeshNavigationTrait" },
66
+ { "class": "/Script/MassMovement.MassMovementTrait" },
67
+ {
68
+ "class": "/Script/MassAIBehavior.MassStateTreeTrait",
69
+ "properties": {
70
+ "StateTree": "/Game/MMOValidation/MassPersistentPawn/ST_MassPersistentPawnWorkerAI.ST_MassPersistentPawnWorkerAI"
71
+ }
72
+ }
73
+ ]
74
+ }
75
+ ```
76
+
77
+ Traits are ordered and unique. Existing assets may be extended only when the
78
+ requested list has the existing list as an exact prefix. Conflicting order,
79
+ duplicate classes, replacement, and removal are rejected. `onConflict` accepts
80
+ `skip`, `error`, or `update` (default). Trait properties use the bridge's
81
+ recursive JSON property conversion, including object and soft-object paths.
82
+
83
+ ## Native asset validation
84
+
85
+ `validate_assets` performs synchronous validation through
86
+ `UEditorValidatorSubsystem::ValidateAssetsWithSettings`; it does not invoke a
87
+ console command or save assets. Use `assetPaths` (an array) or `assetPath` for
88
+ exact package/object paths, or retain the backward-compatible recursive
89
+ `directory` form (default `/Game/`). Explicit package paths must resolve to
90
+ exactly one asset; missing and ambiguous paths fail before validation starts.
91
+
92
+ The successful response includes `selectionMode`, `selection`,
93
+ `validationUsecase`, `requested`, `checked`, `valid`, `invalid`, `skipped`,
94
+ `warnings`, `unableToValidate`, `externalObjects`, `assetLimitReached`, and an
95
+ overall `result`. Ordered `assets[]` details include `objectPath`, package and
96
+ asset names, per-asset result, `errors`, `warnings`, and tokenized `messages`;
97
+ any non-asset tokenized messages are returned in `validatorMessages`.
@@ -26,7 +26,11 @@
26
26
  #include "Async/Async.h"
27
27
  #include "Handlers/EditorHandlers.h"
28
28
  #include "Handlers/AssetHandlers.h"
29
+ #include "Handlers/AssetHandlers_Geometry.h"
30
+ #include "Handlers/AssetHandlers_MeshBoolean.h"
31
+ #include "Handlers/AssetHandlers_BulkRead.h"
29
32
  #include "Handlers/BlueprintHandlers.h"
33
+ #include "Handlers/BlueprintHandlers_Collision.h"
30
34
  #include "Handlers/ProjectHandlers.h"
31
35
  #include "Handlers/LevelHandlers.h"
32
36
  #include "Handlers/ReflectionHandlers.h"
@@ -49,6 +53,8 @@
49
53
  #include "Handlers/StateTreeHandlers.h"
50
54
  #include "Handlers/ChooserHandlers.h"
51
55
  #include "Handlers/EpicHandlers.h"
56
+ #include "Handlers/MassHandlers.h"
57
+ #include "Handlers/SkeletalMeshHandlers.h"
52
58
  #include "Handlers/FabHandlers.h"
53
59
  #include "Handlers/LockHandlers.h"
54
60
  #include "Handlers/DiffHandlers.h"
@@ -129,7 +135,13 @@ FMCPBridgeServer::FMCPBridgeServer(int32 Port, const FString& InPortSource, bool
129
135
  // Register core handlers
130
136
  FEditorHandlers::RegisterHandlers(HandlerRegistry);
131
137
  FAssetHandlers::RegisterHandlers(HandlerRegistry);
138
+ FAssetGeometryHandlers::RegisterHandlers(HandlerRegistry);
139
+ FAssetMeshBooleanHandlers::RegisterHandlers(HandlerRegistry);
140
+ // #909: bulk_read_asset_properties, in its own translation unit so a
141
+ // library-wide read lands without reopening AssetHandlers.cpp.
142
+ FAssetBulkReadHandlers::RegisterHandlers(HandlerRegistry);
132
143
  FBlueprintHandlers::RegisterHandlers(HandlerRegistry);
144
+ FCollisionQueryHandlers::RegisterHandlers(HandlerRegistry);
133
145
  FLevelHandlers::RegisterHandlers(HandlerRegistry);
134
146
  FReflectionHandlers::RegisterHandlers(HandlerRegistry);
135
147
  FGasHandlers::RegisterHandlers(HandlerRegistry);
@@ -152,6 +164,8 @@ FMCPBridgeServer::FMCPBridgeServer(int32 Port, const FString& InPortSource, bool
152
164
  FStateTreeHandlers::RegisterHandlers(HandlerRegistry);
153
165
  FChooserHandlers::RegisterHandlers(HandlerRegistry);
154
166
  FEpicHandlers::RegisterHandlers(HandlerRegistry);
167
+ FMassHandlers::RegisterHandlers(HandlerRegistry);
168
+ FSkeletalMeshHandlers::RegisterHandlers(HandlerRegistry);
155
169
  FFabHandlers::RegisterHandlers(HandlerRegistry);
156
170
  FLockHandlers::RegisterHandlers(HandlerRegistry);
157
171
  FDiffHandlers::RegisterHandlers(HandlerRegistry);
@@ -84,7 +84,18 @@ void FMCPGameThreadExecutor::DrainModalSafeQueue()
84
84
 
85
85
  TSharedPtr<FJsonValue> FMCPGameThreadExecutor::ExecuteOnGameThread(FHandlerFunction Handler, const TSharedPtr<FJsonObject>& Params, float TimeoutSeconds, bool bModalSafe)
86
86
  {
87
- if (!bEditorReady)
87
+ // #968: the readiness gate does not apply to the handlers whose job is to
88
+ // clear a block. A modal raised during startup (the "Restore Packages"
89
+ // prompt after an unclean shutdown) holds the game thread before the editor
90
+ // is ready, and this gate then rejected respond_to_dialog and
91
+ // set_dialog_policy - the two calls that could dismiss it - with "Editor is
92
+ // still initializing", while get_engine_state cheerfully described the
93
+ // dialog down to its button labels because it answers off the game thread.
94
+ // The gate was blocked by the very dialog the call would have dismissed,
95
+ // and the only way out was an OS kill that discarded the user's autosave
96
+ // choice. Modal-safe handlers read or answer the active dialog through
97
+ // Slate and touch nothing that startup has yet to build, so they run.
98
+ if (!bEditorReady && !bModalSafe)
88
99
  {
89
100
  TSharedPtr<FJsonObject> ErrorObject = MakeShared<FJsonObject>();
90
101
  ErrorObject->SetStringField(TEXT("error"), TEXT("Editor is still initializing. Please wait and retry."));
@@ -106,7 +117,7 @@ TSharedPtr<FJsonValue> FMCPGameThreadExecutor::ExecuteOnGameThread(FHandlerFunct
106
117
 
107
118
  // Capture Handler and Params by value so they outlive the caller's stack
108
119
  // if the caller abandons the wait.
109
- auto RunOnce = [State, Handler, Params]()
120
+ auto RunOnce = [State, Handler, Params, bModalSafe]()
110
121
  {
111
122
  // Caller already gave up - skip the work entirely. Python may
112
123
  // still be mid-execution; we cannot safely cancel it, but we
@@ -122,8 +133,14 @@ TSharedPtr<FJsonValue> FMCPGameThreadExecutor::ExecuteOnGameThread(FHandlerFunct
122
133
  return;
123
134
  }
124
135
 
125
- // Safety: verify GEditor is available before running handlers
126
- if (!GEditor)
136
+ // Safety: verify GEditor is available before running handlers.
137
+ //
138
+ // #968: except for the modal-safe ones. They go through Slate and check
139
+ // FSlateApplication for themselves, so GEditor is not something they
140
+ // need, and refusing them here would put the startup deadlock back one
141
+ // layer down: a dialog raised before GEditor exists is exactly the one
142
+ // nothing else can clear.
143
+ if (!GEditor && !bModalSafe)
127
144
  {
128
145
  TSharedPtr<FJsonObject> ErrorObject = MakeShared<FJsonObject>();
129
146
  ErrorObject->SetStringField(TEXT("error"), TEXT("Editor world not ready yet. Retry in a moment."));
@@ -23,6 +23,15 @@ public:
23
23
  // could clear the dialog. Handlers that only read or answer the active
24
24
  // dialog are safe to run in that loop and get unstuck this way; nothing
25
25
  // else should set it.
26
+ //
27
+ // #968: it also exempts the call from the "editor is still initializing"
28
+ // gate and from the GEditor check. A modal raised during startup blocks the
29
+ // game thread before the editor is ever marked ready, so gating the dialog
30
+ // handlers on readiness made the block permanent: the gate was held shut by
31
+ // the dialog those calls exist to dismiss, and the only escape was an OS
32
+ // kill. The two exemptions travel together because they describe one
33
+ // property - this handler is how a blocked engine gets unblocked, so no
34
+ // block may stand in front of it.
26
35
  TSharedPtr<FJsonValue> ExecuteOnGameThread(FHandlerFunction Handler, const TSharedPtr<FJsonObject>& Params, float TimeoutSeconds = 30.0f, bool bModalSafe = false);
27
36
 
28
37
  // Run any modal-safe work that was queued while a dialog blocked the