unreal-engine-mcp-server 0.4.7 → 0.5.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 (438) hide show
  1. package/.env.example +26 -0
  2. package/.env.production +38 -7
  3. package/.eslintrc.json +0 -54
  4. package/.eslintrc.override.json +8 -0
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +94 -0
  6. package/.github/ISSUE_TEMPLATE/config.yml +8 -0
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +56 -0
  8. package/.github/copilot-instructions.md +478 -45
  9. package/.github/dependabot.yml +19 -0
  10. package/.github/labeler.yml +24 -0
  11. package/.github/labels.yml +70 -0
  12. package/.github/pull_request_template.md +42 -0
  13. package/.github/release-drafter.yml +148 -0
  14. package/.github/workflows/auto-merge.yml +38 -0
  15. package/.github/workflows/ci.yml +38 -0
  16. package/.github/workflows/dependency-review.yml +17 -0
  17. package/.github/workflows/gemini-issue-triage.yml +172 -0
  18. package/.github/workflows/greetings.yml +23 -0
  19. package/.github/workflows/labeler.yml +16 -0
  20. package/.github/workflows/links.yml +80 -0
  21. package/.github/workflows/pr-size-labeler.yml +137 -0
  22. package/.github/workflows/publish-mcp.yml +12 -7
  23. package/.github/workflows/release-drafter.yml +23 -0
  24. package/.github/workflows/release.yml +112 -0
  25. package/.github/workflows/semantic-pull-request.yml +35 -0
  26. package/.github/workflows/smoke-test.yml +36 -0
  27. package/.github/workflows/stale.yml +28 -0
  28. package/CHANGELOG.md +267 -31
  29. package/CONTRIBUTING.md +140 -0
  30. package/README.md +166 -71
  31. package/claude_desktop_config_example.json +7 -6
  32. package/dist/automation/bridge.d.ts +50 -0
  33. package/dist/automation/bridge.js +452 -0
  34. package/dist/automation/connection-manager.d.ts +23 -0
  35. package/dist/automation/connection-manager.js +107 -0
  36. package/dist/automation/handshake.d.ts +11 -0
  37. package/dist/automation/handshake.js +89 -0
  38. package/dist/automation/index.d.ts +3 -0
  39. package/dist/automation/index.js +3 -0
  40. package/dist/automation/message-handler.d.ts +12 -0
  41. package/dist/automation/message-handler.js +149 -0
  42. package/dist/automation/request-tracker.d.ts +25 -0
  43. package/dist/automation/request-tracker.js +98 -0
  44. package/dist/automation/types.d.ts +130 -0
  45. package/dist/automation/types.js +2 -0
  46. package/dist/cli.js +32 -5
  47. package/dist/config.d.ts +27 -0
  48. package/dist/config.js +60 -0
  49. package/dist/constants.d.ts +12 -0
  50. package/dist/constants.js +12 -0
  51. package/dist/graphql/resolvers.d.ts +268 -0
  52. package/dist/graphql/resolvers.js +743 -0
  53. package/dist/graphql/schema.d.ts +5 -0
  54. package/dist/graphql/schema.js +437 -0
  55. package/dist/graphql/server.d.ts +26 -0
  56. package/dist/graphql/server.js +115 -0
  57. package/dist/graphql/types.d.ts +7 -0
  58. package/dist/graphql/types.js +2 -0
  59. package/dist/handlers/resource-handlers.d.ts +20 -0
  60. package/dist/handlers/resource-handlers.js +180 -0
  61. package/dist/index.d.ts +31 -18
  62. package/dist/index.js +119 -619
  63. package/dist/prompts/index.js +4 -4
  64. package/dist/resources/actors.d.ts +17 -12
  65. package/dist/resources/actors.js +56 -76
  66. package/dist/resources/assets.d.ts +6 -14
  67. package/dist/resources/assets.js +115 -147
  68. package/dist/resources/levels.d.ts +13 -13
  69. package/dist/resources/levels.js +25 -34
  70. package/dist/server/resource-registry.d.ts +20 -0
  71. package/dist/server/resource-registry.js +37 -0
  72. package/dist/server/tool-registry.d.ts +23 -0
  73. package/dist/server/tool-registry.js +322 -0
  74. package/dist/server-setup.d.ts +21 -0
  75. package/dist/server-setup.js +111 -0
  76. package/dist/services/health-monitor.d.ts +34 -0
  77. package/dist/services/health-monitor.js +105 -0
  78. package/dist/services/metrics-server.d.ts +11 -0
  79. package/dist/services/metrics-server.js +105 -0
  80. package/dist/tools/actors.d.ts +147 -9
  81. package/dist/tools/actors.js +350 -311
  82. package/dist/tools/animation.d.ts +135 -4
  83. package/dist/tools/animation.js +510 -411
  84. package/dist/tools/assets.d.ts +117 -19
  85. package/dist/tools/assets.js +259 -284
  86. package/dist/tools/audio.d.ts +102 -42
  87. package/dist/tools/audio.js +272 -685
  88. package/dist/tools/base-tool.d.ts +17 -0
  89. package/dist/tools/base-tool.js +46 -0
  90. package/dist/tools/behavior-tree.d.ts +94 -0
  91. package/dist/tools/behavior-tree.js +39 -0
  92. package/dist/tools/blueprint/helpers.d.ts +29 -0
  93. package/dist/tools/blueprint/helpers.js +182 -0
  94. package/dist/tools/blueprint.d.ts +228 -118
  95. package/dist/tools/blueprint.js +685 -832
  96. package/dist/tools/consolidated-tool-definitions.d.ts +5462 -1781
  97. package/dist/tools/consolidated-tool-definitions.js +829 -496
  98. package/dist/tools/consolidated-tool-handlers.d.ts +2 -1
  99. package/dist/tools/consolidated-tool-handlers.js +211 -1026
  100. package/dist/tools/debug.d.ts +143 -85
  101. package/dist/tools/debug.js +234 -180
  102. package/dist/tools/dynamic-handler-registry.d.ts +11 -0
  103. package/dist/tools/dynamic-handler-registry.js +101 -0
  104. package/dist/tools/editor.d.ts +139 -18
  105. package/dist/tools/editor.js +239 -244
  106. package/dist/tools/engine.d.ts +10 -4
  107. package/dist/tools/engine.js +13 -5
  108. package/dist/tools/environment.d.ts +36 -0
  109. package/dist/tools/environment.js +267 -0
  110. package/dist/tools/foliage.d.ts +105 -14
  111. package/dist/tools/foliage.js +219 -331
  112. package/dist/tools/handlers/actor-handlers.d.ts +3 -0
  113. package/dist/tools/handlers/actor-handlers.js +232 -0
  114. package/dist/tools/handlers/animation-handlers.d.ts +3 -0
  115. package/dist/tools/handlers/animation-handlers.js +185 -0
  116. package/dist/tools/handlers/argument-helper.d.ts +16 -0
  117. package/dist/tools/handlers/argument-helper.js +80 -0
  118. package/dist/tools/handlers/asset-handlers.d.ts +3 -0
  119. package/dist/tools/handlers/asset-handlers.js +496 -0
  120. package/dist/tools/handlers/audio-handlers.d.ts +3 -0
  121. package/dist/tools/handlers/audio-handlers.js +166 -0
  122. package/dist/tools/handlers/blueprint-handlers.d.ts +4 -0
  123. package/dist/tools/handlers/blueprint-handlers.js +358 -0
  124. package/dist/tools/handlers/common-handlers.d.ts +14 -0
  125. package/dist/tools/handlers/common-handlers.js +56 -0
  126. package/dist/tools/handlers/editor-handlers.d.ts +3 -0
  127. package/dist/tools/handlers/editor-handlers.js +119 -0
  128. package/dist/tools/handlers/effect-handlers.d.ts +3 -0
  129. package/dist/tools/handlers/effect-handlers.js +171 -0
  130. package/dist/tools/handlers/environment-handlers.d.ts +3 -0
  131. package/dist/tools/handlers/environment-handlers.js +170 -0
  132. package/dist/tools/handlers/graph-handlers.d.ts +3 -0
  133. package/dist/tools/handlers/graph-handlers.js +90 -0
  134. package/dist/tools/handlers/input-handlers.d.ts +3 -0
  135. package/dist/tools/handlers/input-handlers.js +21 -0
  136. package/dist/tools/handlers/inspect-handlers.d.ts +3 -0
  137. package/dist/tools/handlers/inspect-handlers.js +383 -0
  138. package/dist/tools/handlers/level-handlers.d.ts +3 -0
  139. package/dist/tools/handlers/level-handlers.js +237 -0
  140. package/dist/tools/handlers/lighting-handlers.d.ts +3 -0
  141. package/dist/tools/handlers/lighting-handlers.js +144 -0
  142. package/dist/tools/handlers/performance-handlers.d.ts +3 -0
  143. package/dist/tools/handlers/performance-handlers.js +130 -0
  144. package/dist/tools/handlers/pipeline-handlers.d.ts +3 -0
  145. package/dist/tools/handlers/pipeline-handlers.js +110 -0
  146. package/dist/tools/handlers/sequence-handlers.d.ts +3 -0
  147. package/dist/tools/handlers/sequence-handlers.js +376 -0
  148. package/dist/tools/handlers/system-handlers.d.ts +4 -0
  149. package/dist/tools/handlers/system-handlers.js +506 -0
  150. package/dist/tools/input.d.ts +19 -0
  151. package/dist/tools/input.js +89 -0
  152. package/dist/tools/introspection.d.ts +103 -40
  153. package/dist/tools/introspection.js +425 -568
  154. package/dist/tools/landscape.d.ts +97 -36
  155. package/dist/tools/landscape.js +280 -409
  156. package/dist/tools/level.d.ts +130 -10
  157. package/dist/tools/level.js +639 -675
  158. package/dist/tools/lighting.d.ts +77 -38
  159. package/dist/tools/lighting.js +441 -943
  160. package/dist/tools/logs.d.ts +3 -3
  161. package/dist/tools/logs.js +5 -57
  162. package/dist/tools/materials.d.ts +91 -24
  163. package/dist/tools/materials.js +190 -118
  164. package/dist/tools/niagara.d.ts +149 -39
  165. package/dist/tools/niagara.js +232 -182
  166. package/dist/tools/performance.d.ts +27 -12
  167. package/dist/tools/performance.js +204 -122
  168. package/dist/tools/physics.d.ts +32 -77
  169. package/dist/tools/physics.js +171 -582
  170. package/dist/tools/property-dictionary.d.ts +13 -0
  171. package/dist/tools/property-dictionary.js +82 -0
  172. package/dist/tools/sequence.d.ts +73 -48
  173. package/dist/tools/sequence.js +196 -748
  174. package/dist/tools/tool-definition-utils.d.ts +59 -0
  175. package/dist/tools/tool-definition-utils.js +35 -0
  176. package/dist/tools/ui.d.ts +66 -34
  177. package/dist/tools/ui.js +134 -214
  178. package/dist/types/env.d.ts +0 -3
  179. package/dist/types/env.js +0 -7
  180. package/dist/types/tool-interfaces.d.ts +898 -0
  181. package/dist/types/tool-interfaces.js +2 -0
  182. package/dist/types/tool-types.d.ts +183 -19
  183. package/dist/types/tool-types.js +0 -4
  184. package/dist/unreal-bridge.d.ts +24 -131
  185. package/dist/unreal-bridge.js +364 -1506
  186. package/dist/utils/command-validator.d.ts +9 -0
  187. package/dist/utils/command-validator.js +67 -0
  188. package/dist/utils/elicitation.d.ts +1 -1
  189. package/dist/utils/elicitation.js +12 -15
  190. package/dist/utils/error-handler.d.ts +2 -51
  191. package/dist/utils/error-handler.js +11 -87
  192. package/dist/utils/ini-reader.d.ts +3 -0
  193. package/dist/utils/ini-reader.js +69 -0
  194. package/dist/utils/logger.js +9 -6
  195. package/dist/utils/normalize.d.ts +3 -0
  196. package/dist/utils/normalize.js +56 -0
  197. package/dist/utils/response-factory.d.ts +7 -0
  198. package/dist/utils/response-factory.js +33 -0
  199. package/dist/utils/response-validator.d.ts +3 -24
  200. package/dist/utils/response-validator.js +130 -81
  201. package/dist/utils/result-helpers.d.ts +4 -5
  202. package/dist/utils/result-helpers.js +15 -16
  203. package/dist/utils/safe-json.js +5 -11
  204. package/dist/utils/unreal-command-queue.d.ts +24 -0
  205. package/dist/utils/unreal-command-queue.js +120 -0
  206. package/dist/utils/validation.d.ts +0 -40
  207. package/dist/utils/validation.js +1 -78
  208. package/dist/wasm/index.d.ts +70 -0
  209. package/dist/wasm/index.js +535 -0
  210. package/docs/GraphQL-API.md +888 -0
  211. package/docs/Migration-Guide-v0.5.0.md +692 -0
  212. package/docs/Roadmap.md +53 -0
  213. package/docs/WebAssembly-Integration.md +628 -0
  214. package/docs/editor-plugin-extension.md +370 -0
  215. package/docs/handler-mapping.md +242 -0
  216. package/docs/native-automation-progress.md +128 -0
  217. package/docs/testing-guide.md +423 -0
  218. package/mcp-config-example.json +6 -6
  219. package/package.json +60 -27
  220. package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +8 -0
  221. package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +64 -0
  222. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +189 -0
  223. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +22 -0
  224. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +30 -0
  225. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +1983 -0
  226. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +72 -0
  227. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +46 -0
  228. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +581 -0
  229. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +2394 -0
  230. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +300 -0
  231. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +2807 -0
  232. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +1087 -0
  233. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +488 -0
  234. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +643 -0
  235. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +31 -0
  236. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +1184 -0
  237. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +5652 -0
  238. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +152 -0
  239. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +2614 -0
  240. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +42 -0
  241. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +1237 -0
  242. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +1701 -0
  243. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +2145 -0
  244. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +954 -0
  245. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +209 -0
  246. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +41 -0
  247. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +1164 -0
  248. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +762 -0
  249. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +634 -0
  250. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +136 -0
  251. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +494 -0
  252. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +278 -0
  253. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +625 -0
  254. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +401 -0
  255. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +67 -0
  256. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +735 -0
  257. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +2634 -0
  258. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +189 -0
  259. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +917 -0
  260. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +39 -0
  261. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +2670 -0
  262. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +519 -0
  263. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +38 -0
  264. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +668 -0
  265. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +346 -0
  266. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +1330 -0
  267. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +149 -0
  268. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +783 -0
  269. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +115 -0
  270. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +796 -0
  271. package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +117 -0
  272. package/scripts/check-unreal-connection.mjs +19 -0
  273. package/scripts/clean-tmp.js +23 -0
  274. package/scripts/patch-wasm.js +26 -0
  275. package/scripts/run-all-tests.mjs +131 -0
  276. package/scripts/smoke-test.ts +94 -0
  277. package/scripts/sync-mcp-plugin.js +143 -0
  278. package/scripts/test-no-plugin-alternates.mjs +113 -0
  279. package/scripts/validate-server.js +46 -0
  280. package/scripts/verify-automation-bridge.js +200 -0
  281. package/server.json +57 -21
  282. package/src/automation/bridge.ts +558 -0
  283. package/src/automation/connection-manager.ts +130 -0
  284. package/src/automation/handshake.ts +99 -0
  285. package/src/automation/index.ts +2 -0
  286. package/src/automation/message-handler.ts +167 -0
  287. package/src/automation/request-tracker.ts +123 -0
  288. package/src/automation/types.ts +107 -0
  289. package/src/cli.ts +33 -6
  290. package/src/config.ts +73 -0
  291. package/src/constants.ts +12 -0
  292. package/src/graphql/resolvers.ts +1010 -0
  293. package/src/graphql/schema.ts +452 -0
  294. package/src/graphql/server.ts +154 -0
  295. package/src/graphql/types.ts +7 -0
  296. package/src/handlers/resource-handlers.ts +186 -0
  297. package/src/index.ts +152 -663
  298. package/src/prompts/index.ts +4 -4
  299. package/src/resources/actors.ts +58 -76
  300. package/src/resources/assets.ts +147 -134
  301. package/src/resources/levels.ts +28 -33
  302. package/src/server/resource-registry.ts +47 -0
  303. package/src/server/tool-registry.ts +354 -0
  304. package/src/server-setup.ts +148 -0
  305. package/src/services/health-monitor.ts +132 -0
  306. package/src/services/metrics-server.ts +142 -0
  307. package/src/tools/actors.ts +417 -322
  308. package/src/tools/animation.ts +671 -461
  309. package/src/tools/assets.ts +353 -289
  310. package/src/tools/audio.ts +323 -766
  311. package/src/tools/base-tool.ts +52 -0
  312. package/src/tools/behavior-tree.ts +45 -0
  313. package/src/tools/blueprint/helpers.ts +189 -0
  314. package/src/tools/blueprint.ts +787 -965
  315. package/src/tools/consolidated-tool-definitions.ts +993 -515
  316. package/src/tools/consolidated-tool-handlers.ts +272 -1139
  317. package/src/tools/debug.ts +292 -187
  318. package/src/tools/dynamic-handler-registry.ts +151 -0
  319. package/src/tools/editor.ts +309 -246
  320. package/src/tools/engine.ts +14 -3
  321. package/src/tools/environment.ts +287 -0
  322. package/src/tools/foliage.ts +314 -379
  323. package/src/tools/handlers/actor-handlers.ts +271 -0
  324. package/src/tools/handlers/animation-handlers.ts +237 -0
  325. package/src/tools/handlers/argument-helper.ts +142 -0
  326. package/src/tools/handlers/asset-handlers.ts +532 -0
  327. package/src/tools/handlers/audio-handlers.ts +194 -0
  328. package/src/tools/handlers/blueprint-handlers.ts +380 -0
  329. package/src/tools/handlers/common-handlers.ts +87 -0
  330. package/src/tools/handlers/editor-handlers.ts +123 -0
  331. package/src/tools/handlers/effect-handlers.ts +220 -0
  332. package/src/tools/handlers/environment-handlers.ts +183 -0
  333. package/src/tools/handlers/graph-handlers.ts +116 -0
  334. package/src/tools/handlers/input-handlers.ts +28 -0
  335. package/src/tools/handlers/inspect-handlers.ts +450 -0
  336. package/src/tools/handlers/level-handlers.ts +252 -0
  337. package/src/tools/handlers/lighting-handlers.ts +147 -0
  338. package/src/tools/handlers/performance-handlers.ts +132 -0
  339. package/src/tools/handlers/pipeline-handlers.ts +127 -0
  340. package/src/tools/handlers/sequence-handlers.ts +415 -0
  341. package/src/tools/handlers/system-handlers.ts +564 -0
  342. package/src/tools/input.ts +101 -0
  343. package/src/tools/introspection.ts +493 -584
  344. package/src/tools/landscape.ts +394 -489
  345. package/src/tools/level.ts +752 -694
  346. package/src/tools/lighting.ts +583 -984
  347. package/src/tools/logs.ts +9 -57
  348. package/src/tools/materials.ts +231 -121
  349. package/src/tools/niagara.ts +293 -168
  350. package/src/tools/performance.ts +320 -168
  351. package/src/tools/physics.ts +268 -613
  352. package/src/tools/property-dictionary.ts +98 -0
  353. package/src/tools/sequence.ts +255 -815
  354. package/src/tools/tool-definition-utils.ts +35 -0
  355. package/src/tools/ui.ts +207 -283
  356. package/src/types/env.ts +0 -10
  357. package/src/types/tool-interfaces.ts +250 -0
  358. package/src/types/tool-types.ts +243 -21
  359. package/src/unreal-bridge.ts +460 -1550
  360. package/src/utils/command-validator.ts +75 -0
  361. package/src/utils/elicitation.ts +10 -7
  362. package/src/utils/error-handler.ts +14 -90
  363. package/src/utils/ini-reader.ts +86 -0
  364. package/src/utils/logger.ts +8 -3
  365. package/src/utils/normalize.ts +60 -0
  366. package/src/utils/response-factory.ts +39 -0
  367. package/src/utils/response-validator.ts +176 -56
  368. package/src/utils/result-helpers.ts +21 -19
  369. package/src/utils/safe-json.ts +14 -11
  370. package/src/utils/unreal-command-queue.ts +152 -0
  371. package/src/utils/validation.ts +4 -1
  372. package/src/wasm/index.ts +838 -0
  373. package/test-server.mjs +100 -0
  374. package/tests/run-unreal-tool-tests.mjs +242 -14
  375. package/tests/test-animation.mjs +44 -0
  376. package/tests/test-asset-advanced.mjs +82 -0
  377. package/tests/test-asset-errors.mjs +35 -0
  378. package/tests/test-audio.mjs +219 -0
  379. package/tests/test-automation-timeouts.mjs +98 -0
  380. package/tests/test-behavior-tree.mjs +261 -0
  381. package/tests/test-blueprint-events.mjs +35 -0
  382. package/tests/test-blueprint-graph.mjs +79 -0
  383. package/tests/test-blueprint.mjs +577 -0
  384. package/tests/test-client-mode.mjs +86 -0
  385. package/tests/test-console-command.mjs +56 -0
  386. package/tests/test-control-actor.mjs +425 -0
  387. package/tests/test-control-editor.mjs +80 -0
  388. package/tests/test-extra-tools.mjs +38 -0
  389. package/tests/test-graphql.mjs +322 -0
  390. package/tests/test-inspect.mjs +72 -0
  391. package/tests/test-landscape.mjs +60 -0
  392. package/tests/test-manage-asset.mjs +438 -0
  393. package/tests/test-manage-level.mjs +70 -0
  394. package/tests/test-materials.mjs +356 -0
  395. package/tests/test-niagara.mjs +185 -0
  396. package/tests/test-no-inline-python.mjs +122 -0
  397. package/tests/test-plugin-handshake.mjs +82 -0
  398. package/tests/test-render.mjs +33 -0
  399. package/tests/test-runner.mjs +933 -0
  400. package/tests/test-search-assets.mjs +66 -0
  401. package/tests/test-sequence.mjs +68 -0
  402. package/tests/test-system.mjs +57 -0
  403. package/tests/test-wasm.mjs +193 -0
  404. package/tests/test-world-partition.mjs +215 -0
  405. package/tsconfig.json +3 -3
  406. package/wasm/Cargo.lock +363 -0
  407. package/wasm/Cargo.toml +42 -0
  408. package/wasm/LICENSE +21 -0
  409. package/wasm/README.md +253 -0
  410. package/wasm/src/dependency_resolver.rs +377 -0
  411. package/wasm/src/lib.rs +153 -0
  412. package/wasm/src/property_parser.rs +271 -0
  413. package/wasm/src/transform_math.rs +396 -0
  414. package/wasm/tests/integration.rs +109 -0
  415. package/.github/workflows/smithery-build.yml +0 -29
  416. package/dist/tools/build_environment_advanced.d.ts +0 -65
  417. package/dist/tools/build_environment_advanced.js +0 -633
  418. package/dist/tools/rc.d.ts +0 -110
  419. package/dist/tools/rc.js +0 -437
  420. package/dist/tools/visual.d.ts +0 -40
  421. package/dist/tools/visual.js +0 -282
  422. package/dist/utils/http.d.ts +0 -6
  423. package/dist/utils/http.js +0 -151
  424. package/dist/utils/python-output.d.ts +0 -18
  425. package/dist/utils/python-output.js +0 -290
  426. package/dist/utils/python.d.ts +0 -2
  427. package/dist/utils/python.js +0 -4
  428. package/dist/utils/stdio-redirect.d.ts +0 -2
  429. package/dist/utils/stdio-redirect.js +0 -20
  430. package/docs/unreal-tool-test-cases.md +0 -574
  431. package/smithery.yaml +0 -29
  432. package/src/tools/build_environment_advanced.ts +0 -732
  433. package/src/tools/rc.ts +0 -515
  434. package/src/tools/visual.ts +0 -281
  435. package/src/utils/http.ts +0 -187
  436. package/src/utils/python-output.ts +0 -351
  437. package/src/utils/python.ts +0 -3
  438. package/src/utils/stdio-redirect.ts +0 -18
@@ -1,12 +1,17 @@
1
1
  import { UnrealBridge } from '../unreal-bridge.js';
2
+ import { AutomationBridge } from '../automation/index.js';
2
3
  import { sanitizeAssetName, validateAssetParams } from '../utils/validation.js';
3
- import { interpretStandardResult, coerceString } from '../utils/result-helpers.js';
4
+
5
+ type Vector3 = [number, number, number];
6
+
4
7
 
5
8
  export class NiagaraTools {
6
- constructor(private bridge: UnrealBridge) {}
9
+ constructor(private bridge: UnrealBridge, private automationBridge?: AutomationBridge) { }
10
+
11
+ setAutomationBridge(automationBridge?: AutomationBridge) { this.automationBridge = automationBridge; }
7
12
 
8
13
  /**
9
- * Create Niagara System (real asset via Python)
14
+ * Create Niagara System
10
15
  */
11
16
  async createSystem(params: {
12
17
  name: string;
@@ -21,58 +26,162 @@ export class NiagaraTools {
21
26
  }>;
22
27
  }) {
23
28
  try {
24
- const path = params.savePath || '/Game/Effects/Niagara';
25
- const python = `
26
- import unreal
27
- import json
28
-
29
- path = r"${path}"
30
- name = r"${params.name}"
31
- full_path = f"{path}/{name}"
32
-
33
- if unreal.EditorAssetLibrary.does_asset_exist(full_path):
34
- print('RESULT:' + json.dumps({'success': True, 'path': full_path, 'existing': True}))
35
- else:
36
- asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
37
- factory = None
38
- try:
39
- factory = unreal.NiagaraSystemFactoryNew()
40
- except Exception:
41
- factory = None
42
-
43
- if factory is None:
44
- print('RESULT:' + json.dumps({'success': False, 'error': 'NiagaraSystemFactoryNew unavailable'}))
45
- else:
46
- asset = asset_tools.create_asset(asset_name=name, package_path=path, asset_class=unreal.NiagaraSystem, factory=factory)
47
- if asset:
48
- unreal.EditorAssetLibrary.save_asset(full_path)
49
- print('RESULT:' + json.dumps({'success': True, 'path': full_path}))
50
- else:
51
- print('RESULT:' + json.dumps({'success': False, 'error': 'AssetTools create_asset failed'}))
52
- `.trim();
53
- const resp = await this.bridge.executePython(python);
54
- const interpreted = interpretStandardResult(resp, {
55
- successMessage: `Niagara system ${params.name} created`,
56
- failureMessage: `Failed to create Niagara system ${params.name}`
57
- });
29
+ if (!this.automationBridge || typeof this.automationBridge.sendAutomationRequest !== 'function') {
30
+ throw new Error('Automation Bridge not available. Niagara system creation requires plugin support.');
31
+ }
32
+
33
+ const path = params.savePath || '/Game/Effects/Niagara';
34
+ const response: any = await this.automationBridge.sendAutomationRequest(
35
+ 'create_niagara_system',
36
+ { name: params.name, savePath: path, template: params.template },
37
+ { timeoutMs: 60000 }
38
+ );
58
39
 
59
- if (!interpreted.success) {
60
- return { success: false, error: interpreted.error ?? interpreted.message };
40
+ if (response && response.success !== false) {
41
+ const result = response.result ?? {};
42
+ const systemName: string = result.systemName ?? params.name;
43
+ const systemPath: string = response.path ?? result.systemPath ?? result.path ?? `${path}/${params.name}`;
44
+ return {
45
+ success: true,
46
+ systemName,
47
+ path: systemPath,
48
+ message: response.message || result.message || `Niagara system ${systemName} created`
49
+ } as const;
61
50
  }
62
51
 
63
- const pathFromPayload = coerceString(interpreted.payload.path) ?? `${path}/${params.name}`;
64
52
  return {
65
- success: true,
66
- path: pathFromPayload,
67
- message: interpreted.message
68
- };
69
- } catch (err) {
70
- return { success: false, error: `Failed to create Niagara system: ${err}` };
53
+ success: false,
54
+ error: response?.error ?? 'CREATE_NIAGARA_SYSTEM_FAILED',
55
+ message: response?.message ?? 'Niagara system creation failed'
56
+ } as const;
57
+ } catch (error) {
58
+ const message = error instanceof Error ? error.message : String(error);
59
+ return { success: false, error: `Failed to create Niagara system: ${message}` } as const;
60
+ }
61
+ }
62
+
63
+ async createEmitter(params: {
64
+ name: string;
65
+ savePath?: string;
66
+ systemPath?: string;
67
+ template?: string;
68
+ }) {
69
+ if (!this.automationBridge || typeof this.automationBridge.sendAutomationRequest !== 'function') {
70
+ return { success: false, error: 'AUTOMATION_BRIDGE_UNAVAILABLE', message: 'createEmitter requires automation bridge' } as const;
71
+ }
72
+
73
+ const requestPayload: Record<string, unknown> = {
74
+ name: params.name,
75
+ savePath: params.savePath ?? '/Game/Effects/Niagara'
76
+ };
77
+ if (params.systemPath) requestPayload.systemPath = params.systemPath;
78
+ if (params.template) requestPayload.template = params.template;
79
+
80
+ try {
81
+ const response: any = await this.automationBridge.sendAutomationRequest('create_niagara_emitter', requestPayload, { timeoutMs: 60000 });
82
+ if (response && response.success !== false) {
83
+ const result = response.result ?? {};
84
+ return {
85
+ success: true,
86
+ emitterPath: response.emitterPath ?? result.emitterPath ?? result.path,
87
+ emitterName: result.emitterName ?? params.name,
88
+ message: response.message || result.message || `Niagara emitter ${params.name} created`
89
+ } as const;
90
+ }
91
+
92
+ return {
93
+ success: false,
94
+ error: response?.error ?? 'CREATE_NIAGARA_EMITTER_FAILED',
95
+ message: response?.message ?? 'Niagara emitter creation failed'
96
+ } as const;
97
+ } catch (error) {
98
+ const message = error instanceof Error ? error.message : String(error);
99
+ return { success: false, error: `Failed to create Niagara emitter: ${message}` } as const;
100
+ }
101
+ }
102
+
103
+ async createRibbon(params: {
104
+ systemPath: string;
105
+ start?: { x: number; y: number; z: number } | [number, number, number];
106
+ end?: { x: number; y: number; z: number } | [number, number, number];
107
+ color?: [number, number, number, number];
108
+ width?: number;
109
+ }) {
110
+ if (!this.automationBridge || typeof this.automationBridge.sendAutomationRequest !== 'function') {
111
+ return { success: false, error: 'AUTOMATION_BRIDGE_UNAVAILABLE', message: 'createRibbon requires automation bridge' } as const;
112
+ }
113
+
114
+ const toVector = (value?: { x: number; y: number; z: number } | Vector3): Vector3 | undefined => {
115
+ if (!value) return undefined;
116
+ if (Array.isArray(value)) return [value[0] ?? 0, value[1] ?? 0, value[2] ?? 0];
117
+ return [value.x ?? 0, value.y ?? 0, value.z ?? 0];
118
+ };
119
+
120
+ const requestPayload: Record<string, unknown> = { systemPath: params.systemPath };
121
+ const start = toVector(params.start);
122
+ const end = toVector(params.end);
123
+ if (start) requestPayload.start = start;
124
+ if (end) requestPayload.end = end;
125
+ if (params.color) requestPayload.color = params.color;
126
+ if (typeof params.width === 'number') requestPayload.width = params.width;
127
+
128
+ try {
129
+ const response: any = await this.automationBridge.sendAutomationRequest('create_niagara_ribbon', requestPayload, { timeoutMs: 60000 });
130
+ if (response && response.success !== false) {
131
+ const result = response.result ?? {};
132
+ return {
133
+ success: true,
134
+ ribbonPath: response.ribbonPath ?? result.ribbonPath ?? result.path,
135
+ message: response.message || result.message || 'Niagara ribbon created'
136
+ } as const;
137
+ }
138
+
139
+ return {
140
+ success: false,
141
+ error: response?.error ?? 'CREATE_NIAGARA_RIBBON_FAILED',
142
+ message: response?.message ?? 'Niagara ribbon creation failed'
143
+ } as const;
144
+ } catch (error) {
145
+ const message = error instanceof Error ? error.message : String(error);
146
+ return { success: false, error: `Failed to create Niagara ribbon: ${message}` } as const;
147
+ }
148
+ }
149
+
150
+ async cleanupEffects(params: { filter: string }) {
151
+ if (!this.automationBridge || typeof this.automationBridge.sendAutomationRequest !== 'function') {
152
+ return { success: false, error: 'AUTOMATION_BRIDGE_UNAVAILABLE', message: 'cleanupEffects requires automation bridge' } as const;
153
+ }
154
+ if (!params.filter || typeof params.filter !== 'string') {
155
+ return { success: false, error: 'INVALID_ARGUMENT', message: 'filter is required' } as const;
156
+ }
157
+
158
+ try {
159
+ const response: any = await this.automationBridge.sendAutomationRequest('cleanup', { filter: params.filter }, { timeoutMs: 60000 });
160
+ if (response && response.success !== false) {
161
+ const result = response.result ?? {};
162
+ const removedActors: string[] = result.removedActors ?? response.removedActors ?? [];
163
+ const removedCount = result.removed ?? removedActors.length;
164
+ return {
165
+ success: true,
166
+ removed: removedCount,
167
+ removedActors,
168
+ message: response.message || result.message || `Cleanup completed (removed=${removedCount})`
169
+ } as const;
170
+ }
171
+
172
+ return {
173
+ success: false,
174
+ error: response?.error ?? 'CLEANUP_FAILED',
175
+ message: response?.message ?? 'Niagara cleanup failed'
176
+ } as const;
177
+ } catch (error) {
178
+ const message = error instanceof Error ? error.message : String(error);
179
+ return { success: false, error: `Failed to cleanup Niagara effects: ${message}` } as const;
71
180
  }
72
181
  }
73
182
 
74
183
  /**
75
- * Add Emitter to System (left as-is; console commands may be placeholders)
184
+ * Add Emitter to System
76
185
  */
77
186
  async addEmitter(params: {
78
187
  systemName: string;
@@ -89,43 +198,103 @@ else:
89
198
  mesh?: string;
90
199
  };
91
200
  }) {
201
+ if (!this.automationBridge || typeof this.automationBridge.sendAutomationRequest !== 'function') {
202
+ return { success: false, error: 'AUTOMATION_BRIDGE_UNAVAILABLE', message: 'addEmitter requires automation bridge' } as const;
203
+ }
204
+
92
205
  try {
93
- const commands = [
94
- `AddNiagaraEmitter ${params.systemName} ${params.emitterName} ${params.emitterType}`
95
- ];
96
- if (params.properties) {
97
- const props = params.properties;
98
- if (props.spawnRate !== undefined) {
99
- commands.push(`SetEmitterSpawnRate ${params.systemName} ${params.emitterName} ${props.spawnRate}`);
100
- }
101
- if (props.lifetime !== undefined) {
102
- commands.push(`SetEmitterLifetime ${params.systemName} ${params.emitterName} ${props.lifetime}`);
103
- }
104
- if (props.velocityMin && props.velocityMax) {
105
- const min = props.velocityMin; const max = props.velocityMax;
106
- commands.push(`SetEmitterVelocity ${params.systemName} ${params.emitterName} ${min[0]} ${min[1]} ${min[2]} ${max[0]} ${max[1]} ${max[2]}`);
107
- }
108
- if (props.size !== undefined) {
109
- commands.push(`SetEmitterSize ${params.systemName} ${params.emitterName} ${props.size}`);
110
- }
111
- if (props.color) {
112
- const color = props.color;
113
- commands.push(`SetEmitterColor ${params.systemName} ${params.emitterName} ${color[0]} ${color[1]} ${color[2]} ${color[3]}`);
114
- }
115
- if (props.material) {
116
- commands.push(`SetEmitterMaterial ${params.systemName} ${params.emitterName} ${props.material}`);
117
- }
118
- if (props.mesh && params.emitterType === 'Mesh') {
119
- commands.push(`SetEmitterMesh ${params.systemName} ${params.emitterName} ${props.mesh}`);
120
- }
206
+ const resp: any = await this.automationBridge.sendAutomationRequest('manage_niagara_graph', {
207
+ subAction: 'add_emitter',
208
+ systemName: params.systemName,
209
+ emitterName: params.emitterName,
210
+ emitterType: params.emitterType,
211
+ properties: params.properties
212
+ });
213
+
214
+ if (resp && resp.success !== false) {
215
+ return {
216
+ success: true,
217
+ message: resp.message || `Emitter ${params.emitterName} added to ${params.systemName}`,
218
+ emitterId: resp.result?.emitterId
219
+ };
121
220
  }
122
- await this.bridge.executeConsoleCommands(commands);
123
- return { success: true, message: `Emitter ${params.emitterName} added to ${params.systemName}` };
124
- } catch (err) {
125
- return { success: false, error: `Failed to add emitter: ${err}` };
221
+
222
+ return {
223
+ success: false,
224
+ error: resp?.error || 'ADD_EMITTER_FAILED',
225
+ message: resp?.message || 'Failed to add emitter'
226
+ };
227
+ } catch (e) {
228
+ const message = e instanceof Error ? e.message : String(e);
229
+ return { success: false, error: 'ADD_EMITTER_FAILED', message };
126
230
  }
127
231
  }
128
232
 
233
+ async addModule(params: {
234
+ systemPath: string;
235
+ modulePath: string;
236
+ emitterName?: string;
237
+ scriptType?: 'Spawn' | 'Update';
238
+ timeoutMs?: number;
239
+ }) {
240
+ if (!params.systemPath) return { success: false, error: 'INVALID_SYSTEM_PATH', message: 'System path is required' } as const;
241
+ if (!params.modulePath) return { success: false, error: 'INVALID_MODULE_PATH', message: 'Module path is required' } as const;
242
+
243
+ const res = await this.automationBridge?.sendAutomationRequest('manage_niagara_graph', {
244
+ subAction: 'add_module',
245
+ assetPath: params.systemPath,
246
+ modulePath: params.modulePath,
247
+ emitterName: params.emitterName,
248
+ scriptType: params.scriptType
249
+ });
250
+ return res;
251
+ }
252
+
253
+ async connectPins(params: {
254
+ systemPath: string;
255
+ fromNodeId: string;
256
+ fromPinName: string;
257
+ toNodeId: string;
258
+ toPinName: string;
259
+ emitterName?: string;
260
+ scriptType?: 'Spawn' | 'Update';
261
+ timeoutMs?: number;
262
+ }) {
263
+ if (!params.systemPath) return { success: false, error: 'INVALID_SYSTEM_PATH', message: 'System path is required' } as const;
264
+
265
+ const res = await this.automationBridge?.sendAutomationRequest('manage_niagara_graph', {
266
+ subAction: 'connect_pins',
267
+ assetPath: params.systemPath,
268
+ fromNode: params.fromNodeId,
269
+ fromPin: params.fromPinName,
270
+ toNode: params.toNodeId,
271
+ toPin: params.toPinName,
272
+ emitterName: params.emitterName,
273
+ scriptType: params.scriptType
274
+ });
275
+ return res;
276
+ }
277
+
278
+ async removeNode(params: {
279
+ systemPath: string;
280
+ nodeId: string;
281
+ emitterName?: string;
282
+ scriptType?: 'Spawn' | 'Update';
283
+ timeoutMs?: number;
284
+ }) {
285
+ if (!params.systemPath) return { success: false, error: 'INVALID_SYSTEM_PATH', message: 'System path is required' } as const;
286
+ if (!params.nodeId) return { success: false, error: 'INVALID_NODE_ID', message: 'Node ID is required' } as const;
287
+
288
+ const res = await this.automationBridge?.sendAutomationRequest('manage_niagara_graph', {
289
+ subAction: 'remove_node',
290
+ assetPath: params.systemPath,
291
+ nodeId: params.nodeId,
292
+ emitterName: params.emitterName,
293
+ scriptType: params.scriptType
294
+ });
295
+ return res;
296
+ }
297
+
129
298
  async setParameter(params: {
130
299
  systemName: string;
131
300
  parameterName: string;
@@ -133,17 +302,29 @@ else:
133
302
  value: any;
134
303
  isUserParameter?: boolean;
135
304
  }) {
305
+ // Note: This uses 'set_niagara_parameter' top-level action, OR 'manage_niagara_graph' with subAction 'set_parameter'.
306
+ // The previous implementation used 'set_niagara_parameter'.
307
+ // The C++ 'manage_niagara_graph' also has 'set_parameter'.
308
+ // I will keep existing logic if it works, or switch to manage_niagara_graph if preferred.
309
+ // Given the audit, 'manage_niagara_graph' is the graph-based one.
310
+ // The existing setParameter uses 'set_niagara_parameter' which might be instance-based?
311
+ // Let's stick to existing unless broken, but I'll add the graph-based one as setGraphParameter?
312
+ // User requested "implement all missing". I'll stick to adding missing graph methods I just verified.
313
+
136
314
  try {
137
- const paramType = params.isUserParameter ? 'User' : 'System';
138
- let valueStr = '';
139
- switch (params.parameterType) {
140
- case 'Float': case 'Int': case 'Bool': valueStr = String(params.value); break;
141
- case 'Vector': { const v = params.value as number[]; valueStr = `${v[0]} ${v[1]} ${v[2]}`; break; }
142
- case 'Color': { const c = params.value as number[]; valueStr = `${c[0]} ${c[1]} ${c[2]} ${c[3] || 1}`; break; }
315
+ const automationBridge = (this.bridge as any).automationBridge;
316
+ if (!automationBridge) {
317
+ return { success: false, error: 'Automation bridge not available' };
143
318
  }
144
- const command = `SetNiagara${paramType}Parameter ${params.systemName} ${params.parameterName} ${params.parameterType} ${valueStr}`;
145
- await this.bridge.executeConsoleCommand(command);
146
- return { success: true, message: `Parameter ${params.parameterName} set on ${params.systemName}` };
319
+ const resp: any = await automationBridge.sendAutomationRequest('set_niagara_parameter', {
320
+ systemName: params.systemName,
321
+ parameterName: params.parameterName,
322
+ parameterType: params.parameterType,
323
+ value: params.value,
324
+ isUserParameter: params.isUserParameter === true
325
+ });
326
+ if (resp && resp.success !== false) return { success: true, message: resp.message || `Parameter ${params.parameterName} set on ${params.systemName}`, applied: resp.applied ?? resp.result?.applied } as any;
327
+ return { success: false, message: resp?.message ?? 'Set parameter failed', error: resp?.error ?? 'SET_PARAMETER_FAILED' } as any;
147
328
  } catch (err) {
148
329
  return { success: false, error: `Failed to set parameter: ${err}` };
149
330
  }
@@ -162,7 +343,7 @@ else:
162
343
  }) {
163
344
  try {
164
345
  // Validate effect type at runtime (inputs can come from JSON)
165
- const allowedTypes = ['Fire','Smoke','Explosion','Water','Rain','Snow','Magic','Lightning','Dust','Steam'];
346
+ const allowedTypes = ['Fire', 'Smoke', 'Explosion', 'Water', 'Rain', 'Snow', 'Magic', 'Lightning', 'Dust', 'Steam', 'Default'];
166
347
  if (!params || !allowedTypes.includes(String(params.effectType))) {
167
348
  return { success: false, error: `Invalid effectType: ${String(params?.effectType)}` };
168
349
  }
@@ -184,29 +365,7 @@ else:
184
365
  return { success: false, error: createRes.error || 'Failed creating Niagara system' };
185
366
  }
186
367
 
187
- // Verify existence via Python to avoid RC EditorAssetLibrary issues
188
- const verifyPy = `
189
- import unreal
190
- import json
191
-
192
- p = r"${fullPath}"
193
- exists = bool(unreal.EditorAssetLibrary.does_asset_exist(p))
194
- print('RESULT:' + json.dumps({'success': True, 'exists': exists}))
195
- `.trim();
196
- const verifyResp = await this.bridge.executePython(verifyPy);
197
- const verifyResult = interpretStandardResult(verifyResp, {
198
- successMessage: 'Niagara asset verification complete',
199
- failureMessage: `Failed to verify Niagara asset at ${fullPath}`
200
- });
201
-
202
- if (!verifyResult.success) {
203
- return { success: false, error: verifyResult.error ?? verifyResult.message };
204
- }
205
-
206
- if (verifyResult.payload.exists === false) {
207
- return { success: false, error: `Asset not found after creation: ${fullPath}` };
208
- }
209
-
368
+ // Asset created successfully
210
369
  return { success: true, message: `${params.effectType} effect ${safeName} created`, path: fullPath };
211
370
  } catch (err) {
212
371
  return { success: false, error: `Failed to create effect: ${err}` };
@@ -235,7 +394,7 @@ print('RESULT:' + json.dumps({'success': True, 'exists': exists}))
235
394
  if (s.gridResolution) { const r = s.gridResolution; commands.push(`SetGPUGridResolution ${params.name} ${r[0]} ${r[1]} ${r[2]}`); }
236
395
  if (s.iterations !== undefined) commands.push(`SetGPUIterations ${params.name} ${s.iterations}`);
237
396
  }
238
- await this.bridge.executeConsoleCommands(commands);
397
+ await this.bridge.executeConsoleCommands(commands);
239
398
  return { success: true, message: `GPU simulation ${params.name} created`, path: `${path}/${params.name}` };
240
399
  } catch (err) {
241
400
  return { success: false, error: `Failed to create GPU simulation: ${err}` };
@@ -243,7 +402,7 @@ print('RESULT:' + json.dumps({'success': True, 'exists': exists}))
243
402
  }
244
403
 
245
404
  /**
246
- * Spawn Niagara Effect in Level using Python (NiagaraActor)
405
+ * Spawn Niagara Effect in Level (NiagaraActor)
247
406
  */
248
407
  async spawnEffect(params: {
249
408
  systemPath: string;
@@ -255,61 +414,27 @@ print('RESULT:' + json.dumps({'success': True, 'exists': exists}))
255
414
  }) {
256
415
  try {
257
416
  const loc = Array.isArray(params.location) ? { x: params.location[0], y: params.location[1], z: params.location[2] } : params.location;
258
- const rot = params.rotation || [0, 0, 0];
259
- const scl = Array.isArray(params.scale) ? params.scale : (typeof params.scale === 'number' ? [params.scale, params.scale, params.scale] : [1, 1, 1]);
260
- const py = `
261
- import unreal
262
- import json
263
-
264
- loc = unreal.Vector(${loc.x || 0}, ${loc.y || 0}, ${loc.z || 0})
265
- rot = unreal.Rotator(${rot[0]}, ${rot[1]}, ${rot[2]})
266
- scale = unreal.Vector(${scl[0]}, ${scl[1]}, ${scl[2]})
267
- sys_path = r"${params.systemPath}"
268
-
269
- if unreal.EditorAssetLibrary.does_asset_exist(sys_path):
270
- sys = unreal.EditorAssetLibrary.load_asset(sys_path)
271
- actor_subsystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
272
- actor = actor_subsystem.spawn_actor_from_class(unreal.NiagaraActor, loc, rot)
273
- if actor:
274
- comp = actor.get_niagara_component()
275
- try:
276
- comp.set_asset(sys)
277
- except Exception:
278
- try:
279
- comp.set_editor_property('asset', sys)
280
- except Exception:
281
- pass
282
- comp.set_world_scale3d(scale)
283
- comp.activate(True)
284
- actor.set_actor_label(f"Niagara_{unreal.SystemLibrary.get_game_time_in_seconds(actor.get_world()):.0f}")
285
- print('RESULT:' + json.dumps({'success': True, 'actor': actor.get_actor_label()}))
286
- else:
287
- print('RESULT:' + json.dumps({'success': False, 'error': 'Failed to spawn NiagaraActor'}))
288
- else:
289
- print('RESULT:' + json.dumps({'success': False, 'error': 'System asset not found'}))
290
- `.trim();
291
- const resp = await this.bridge.executePython(py);
292
- const interpreted = interpretStandardResult(resp, {
293
- successMessage: 'Niagara effect spawned',
294
- failureMessage: 'Failed to spawn Niagara effect'
295
- });
296
-
297
- const actorLabel = coerceString(interpreted.payload.actor);
298
-
299
- if (!interpreted.success) {
300
- return { success: false, error: interpreted.error ?? interpreted.message };
301
- }
302
-
303
- const outcome: { success: true; message: string; actor?: string } = {
304
- success: true,
305
- message: interpreted.message
306
- };
307
-
308
- if (actorLabel) {
309
- outcome.actor = actorLabel;
310
- }
417
+ // Prefer plugin transport when available
418
+ if (this.automationBridge && typeof this.automationBridge.sendAutomationRequest === 'function') {
419
+ try {
420
+ const resp: any = await this.automationBridge.sendAutomationRequest('spawn_niagara', {
421
+ systemPath: params.systemPath,
422
+ location: [loc.x ?? 0, loc.y ?? 0, loc.z ?? 0],
423
+ rotation: params.rotation,
424
+ scale: params.scale,
425
+ autoDestroy: params.autoDestroy,
426
+ attachToActor: params.attachToActor
427
+ });
428
+ if (resp && resp.success !== false) {
429
+ return { success: true, message: resp.message || 'Niagara effect spawned', actor: resp.actor || resp.result?.actor || resp.result?.actorName } as any;
430
+ }
431
+ return { success: false, message: resp?.message ?? 'Spawn failed', error: resp?.error ?? 'SPAWN_FAILED' } as any;
432
+ } catch (error) {
433
+ return { success: false, error: `Failed to spawn effect: ${error instanceof Error ? error.message : String(error)}` };
434
+ }
435
+ }
311
436
 
312
- return outcome;
437
+ throw new Error('Automation Bridge not available. Niagara effect spawning requires plugin support.');
313
438
  } catch (err) {
314
439
  return { success: false, error: `Failed to spawn effect: ${err}` };
315
440
  }