unreal-engine-mcp-server 0.4.7 → 0.5.1

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