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,16 +1,13 @@
1
- import { bestEffortInterpretedText, coerceBoolean, coerceNumber, coerceString, interpretStandardResult } from '../utils/result-helpers.js';
1
+ import { coerceBoolean, coerceNumber, coerceString } from '../utils/result-helpers.js';
2
2
  export class FoliageTools {
3
3
  bridge;
4
- constructor(bridge) {
4
+ automationBridge;
5
+ constructor(bridge, automationBridge) {
5
6
  this.bridge = bridge;
7
+ this.automationBridge = automationBridge;
6
8
  }
7
- // NOTE: We intentionally avoid issuing Unreal console commands here because
8
- // they have proven unreliable and generate engine warnings (failed FindConsoleObject).
9
- // Instead, we validate inputs and return structured results. Actual foliage
10
- // authoring should be implemented via Python APIs in future iterations.
11
- // Add foliage type via Python (creates FoliageType asset properly)
9
+ setAutomationBridge(automationBridge) { this.automationBridge = automationBridge; }
12
10
  async addFoliageType(params) {
13
- // Basic validation to prevent bad inputs like 'undefined' and empty strings
14
11
  const errors = [];
15
12
  const name = String(params?.name ?? '').trim();
16
13
  const meshPath = String(params?.meshPath ?? '').trim();
@@ -35,194 +32,58 @@ export class FoliageTools {
35
32
  if (errors.length > 0) {
36
33
  return { success: false, error: errors.join('; ') };
37
34
  }
38
- const py = `
39
- import unreal, json
40
-
41
- name = ${JSON.stringify(name)}
42
- mesh_path = ${JSON.stringify(meshPath)}
43
- fallback_mesh = '/Engine/EngineMeshes/Sphere'
44
- package_path = '/Game/Foliage/Types'
45
-
46
- res = {'success': False, 'created': False, 'asset_path': '', 'used_mesh': '', 'exists_after': False, 'method': '', 'note': ''}
47
-
48
- try:
49
- # Ensure package directory
50
- try:
51
- if not unreal.EditorAssetLibrary.does_directory_exist(package_path):
52
- unreal.EditorAssetLibrary.make_directory(package_path)
53
- except Exception as e:
54
- res['note'] += f"; make_directory failed: {e}"
55
-
56
- # Load mesh or fallback
57
- mesh = None
58
- try:
59
- if unreal.EditorAssetLibrary.does_asset_exist(mesh_path):
60
- mesh = unreal.EditorAssetLibrary.load_asset(mesh_path)
61
- except Exception as e:
62
- res['note'] += f"; could not check/load mesh_path: {e}"
63
-
64
- if not mesh:
65
- mesh = unreal.EditorAssetLibrary.load_asset(fallback_mesh)
66
- res['note'] += '; fallback_mesh_used'
67
- if mesh:
68
- res['used_mesh'] = str(mesh.get_path_name())
69
-
70
- # Create FoliageType asset using proper UE5 API
71
- asset = None
72
- try:
73
- asset_path = f"{package_path}/{name}"
74
-
75
- # Check if asset already exists
76
- if unreal.EditorAssetLibrary.does_asset_exist(asset_path):
77
- asset = unreal.EditorAssetLibrary.load_asset(asset_path)
78
- res['note'] += '; loaded_existing'
79
- else:
80
- # Create FoliageType_InstancedStaticMesh using proper API
81
- try:
82
- asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
83
-
84
- # Try to create factory and set mesh property
85
- factory = None
86
- try:
87
- factory = unreal.FoliageType_InstancedStaticMeshFactory()
88
- # Try different property names for different UE versions
89
- try:
90
- factory.set_editor_property('mesh', mesh)
91
- except:
92
- try:
93
- factory.set_editor_property('static_mesh', mesh)
94
- except:
95
- try:
96
- factory.set_editor_property('source_mesh', mesh)
97
- except:
98
- pass # Factory will use default or no mesh
99
- except:
100
- res['note'] += '; factory_creation_failed'
101
- factory = None
102
-
103
- # Create the asset with or without factory
104
- if factory:
105
- asset = asset_tools.create_asset(
106
- asset_name=name,
107
- package_path=package_path,
108
- asset_class=unreal.FoliageType_InstancedStaticMesh,
109
- factory=factory
110
- )
111
- else:
112
- # Try without factory
113
- asset = asset_tools.create_asset(
114
- asset_name=name,
115
- package_path=package_path,
116
- asset_class=unreal.FoliageType_InstancedStaticMesh,
117
- factory=None
118
- )
119
-
120
- if asset:
121
- # Configure foliage properties
122
- asset.set_editor_property('mesh', mesh)
123
- if ${params.density !== undefined ? params.density : 1.0} >= 0:
124
- asset.set_editor_property('density', ${params.density !== undefined ? params.density : 1.0})
125
- if ${params.randomYaw === false ? 'False' : 'True'}:
126
- asset.set_editor_property('random_yaw', True)
127
- if ${params.alignToNormal === false ? 'False' : 'True'}:
128
- asset.set_editor_property('align_to_normal', True)
129
-
130
- # Set scale range
131
- min_scale = ${params.minScale || 0.8}
132
- max_scale = ${params.maxScale || 1.2}
133
- asset.set_editor_property('scale_x', (min_scale, max_scale))
134
- asset.set_editor_property('scale_y', (min_scale, max_scale))
135
- asset.set_editor_property('scale_z', (min_scale, max_scale))
136
-
137
- res['note'] += '; created_with_factory'
138
- else:
139
- res['note'] += '; factory_creation_failed'
140
- except AttributeError:
141
- # Fallback if factory doesn't exist - use base FoliageType
142
- try:
143
- asset = asset_tools.create_asset(
144
- asset_name=name,
145
- package_path=package_path,
146
- asset_class=unreal.FoliageType,
147
- factory=None
148
- )
149
- if asset:
150
- res['note'] += '; created_base_foliage_type'
151
- except Exception as e2:
152
- res['note'] += f"; base_creation_failed: {e2}"
153
- except Exception as e:
154
- res['note'] += f"; factory_creation_failed: {e}"
155
- asset = None
156
- except Exception as e:
157
- res['note'] += f"; create_asset failed: {e}"
158
- asset = None
159
-
160
- if asset and mesh:
161
- try:
162
- # Set the mesh property (different property names in different UE versions)
163
- try:
164
- asset.set_editor_property('mesh', mesh)
165
- except:
166
- try:
167
- asset.set_editor_property('static_mesh', mesh)
168
- except:
169
- pass
170
-
171
- # Save the asset
172
- unreal.EditorAssetLibrary.save_asset(asset.get_path_name())
173
- res['asset_path'] = str(asset.get_path_name())
174
- res['created'] = True
175
- res['method'] = 'FoliageType_InstancedStaticMesh'
176
- except Exception as e:
177
- res['note'] += f"; set/save asset failed: {e}"
178
- elif not asset:
179
- res['note'] += "; asset creation returned None"
180
- elif not mesh:
181
- res['note'] += "; mesh object is None, cannot assign to foliage type"
182
-
183
- # Verify existence
184
- res['exists_after'] = unreal.EditorAssetLibrary.does_asset_exist(res['asset_path']) if res['asset_path'] else False
185
- res['success'] = res['exists_after'] or res['created']
186
-
187
- except Exception as e:
188
- res['success'] = False
189
- res['note'] += f"; fatal: {e}"
190
-
191
- print('RESULT:' + json.dumps(res))
192
- `.trim();
193
- const pyResp = await this.bridge.executePython(py);
194
- const interpreted = interpretStandardResult(pyResp, {
195
- successMessage: `Foliage type '${name}' processed`,
196
- failureMessage: 'Add foliage type failed'
197
- });
198
- if (!interpreted.success) {
35
+ if (!this.automationBridge) {
36
+ throw new Error('Automation Bridge not available. Foliage operations require plugin support.');
37
+ }
38
+ try {
39
+ const base = meshPath.includes('.') ? meshPath : `${meshPath}.${meshPath.split('/').filter(Boolean).pop()}`;
40
+ const response = await this.automationBridge.sendAutomationRequest('add_foliage_type', {
41
+ name,
42
+ meshPath: base,
43
+ density: params.density ?? 100,
44
+ radius: params.radius ?? 0,
45
+ minScale: params.minScale ?? 1.0,
46
+ maxScale: params.maxScale ?? 1.0,
47
+ alignToNormal: params.alignToNormal ?? true,
48
+ randomYaw: params.randomYaw ?? true,
49
+ groundSlope: params.groundSlope ?? 45
50
+ }, {
51
+ timeoutMs: 60000
52
+ });
53
+ if (response.success === false) {
54
+ return {
55
+ success: false,
56
+ error: response.error || response.message || 'Add foliage type failed',
57
+ note: coerceString(response.result?.note)
58
+ };
59
+ }
60
+ const payload = response.result;
61
+ const created = coerceBoolean(payload.created, false) ?? false;
62
+ const exists = coerceBoolean(payload.exists_after, false) ?? created;
63
+ const method = coerceString(payload.method) ?? 'Unknown';
64
+ const assetPath = coerceString(payload.asset_path);
65
+ const usedMesh = coerceString(payload.used_mesh);
66
+ const note = coerceString(payload.note);
67
+ return {
68
+ success: true,
69
+ created,
70
+ exists,
71
+ method,
72
+ assetPath,
73
+ usedMesh,
74
+ note,
75
+ message: exists
76
+ ? `Foliage type '${name}' ready (${method})`
77
+ : `Created foliage '${name}' but verification did not find it yet`
78
+ };
79
+ }
80
+ catch (error) {
199
81
  return {
200
82
  success: false,
201
- error: coerceString(interpreted.payload.note) ?? interpreted.error ?? 'Add foliage type failed',
202
- note: coerceString(interpreted.payload.note) ?? bestEffortInterpretedText(interpreted)
83
+ error: `Failed to add foliage type: ${error instanceof Error ? error.message : String(error)}`
203
84
  };
204
85
  }
205
- const payload = interpreted.payload;
206
- const created = coerceBoolean(payload.created, false) ?? false;
207
- const exists = coerceBoolean(payload.exists_after, false) ?? created;
208
- const method = coerceString(payload.method) ?? 'Unknown';
209
- const assetPath = coerceString(payload.asset_path);
210
- const usedMesh = coerceString(payload.used_mesh);
211
- const note = coerceString(payload.note);
212
- return {
213
- success: true,
214
- created,
215
- exists,
216
- method,
217
- assetPath,
218
- usedMesh,
219
- note,
220
- message: exists
221
- ? `Foliage type '${name}' ready (${method})`
222
- : `Created foliage '${name}' but verification did not find it yet`
223
- };
224
86
  }
225
- // Paint foliage by placing HISM instances (editor-only)
226
87
  async paintFoliage(params) {
227
88
  const errors = [];
228
89
  const foliageType = String(params?.foliageType ?? '').trim();
@@ -246,131 +107,92 @@ print('RESULT:' + json.dumps(res))
246
107
  if (errors.length > 0) {
247
108
  return { success: false, error: errors.join('; ') };
248
109
  }
249
- const brush = Number.isFinite(params.brushSize) ? params.brushSize : 300;
250
- const py = `
251
- import unreal, json, random, math
252
-
253
- res = {'success': False, 'added': 0, 'actor': '', 'component': '', 'used_mesh': '', 'note': ''}
254
- foliage_type_name = ${JSON.stringify(foliageType)}
255
- px, py, pz = ${pos[0]}, ${pos[1]}, ${pos[2]}
256
- radius = float(${brush}) / 2.0
257
-
258
- try:
259
- actor_subsystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
260
- if not actor_subsystem:
261
- raise RuntimeError('EditorActorSubsystem unavailable. Enable Editor Scripting Utilities plugin.')
262
-
263
- all_actors = actor_subsystem.get_all_level_actors()
264
-
265
- # Find or create a container actor using modern EditorActorSubsystem
266
- label = f"FoliageContainer_{foliage_type_name}"
267
- container = None
268
- for a in all_actors:
269
- try:
270
- if a and a.get_actor_label() == label:
271
- container = a
272
- break
273
- except Exception:
274
- pass
275
-
276
- if not container:
277
- container = actor_subsystem.spawn_actor_from_class(
278
- unreal.StaticMeshActor,
279
- unreal.Vector(px, py, pz)
280
- )
281
- if not container:
282
- raise RuntimeError('Failed to spawn foliage container actor via EditorActorSubsystem')
283
- try:
284
- container.set_actor_label(label)
285
- except Exception:
286
- pass
287
-
288
- # Resolve mesh from FoliageType asset
289
- mesh = None
290
- fol_asset_path = f"/Game/Foliage/Types/{foliage_type_name}.{foliage_type_name}"
291
- if unreal.EditorAssetLibrary.does_asset_exist(fol_asset_path):
292
- try:
293
- ft_asset = unreal.EditorAssetLibrary.load_asset(fol_asset_path)
294
- mesh = ft_asset.get_editor_property('mesh')
295
- except Exception:
296
- mesh = None
297
-
298
- if not mesh:
299
- mesh = unreal.EditorAssetLibrary.load_asset('/Engine/EngineMeshes/Sphere')
300
- res['note'] += '; used_fallback_mesh'
301
-
302
- if mesh:
303
- res['used_mesh'] = str(mesh.get_path_name())
304
-
305
- # Since HISM components and add_component don't work in this version,
306
- # spawn individual StaticMeshActors for each instance
307
- target_count = max(5, int(radius / 20.0))
308
- added = 0
309
- for i in range(target_count):
310
- ang = random.random() * math.tau
311
- r = random.random() * radius
312
- x, y, z = px + math.cos(ang) * r, py + math.sin(ang) * r, pz
313
- try:
314
- # Spawn static mesh actor at position using modern subsystem
315
- inst_actor = actor_subsystem.spawn_actor_from_class(
316
- unreal.StaticMeshActor,
317
- unreal.Vector(x, y, z),
318
- unreal.Rotator(0, random.random()*360.0, 0)
319
- )
320
- if inst_actor and mesh:
321
- # Set mesh on the actor's component
322
- try:
323
- mesh_comp = inst_actor.static_mesh_component
324
- if mesh_comp:
325
- mesh_comp.set_static_mesh(mesh)
326
- inst_actor.set_actor_label(f"{foliage_type_name}_instance_{i}")
327
- # Group under the container for organization
328
- inst_actor.attach_to_actor(container, "", unreal.AttachmentRule.KEEP_WORLD, unreal.AttachmentRule.KEEP_WORLD, unreal.AttachmentRule.KEEP_WORLD, False)
329
- added += 1
330
- except Exception as e:
331
- res['note'] += f"; instance_{i} setup failed: {e}"
332
- except Exception as e:
333
- res['note'] += f"; spawn instance_{i} failed: {e}"
334
-
335
- res['added'] = added
336
- res['actor'] = container.get_actor_label()
337
- res['component'] = 'StaticMeshActors' # Using actors instead of components
338
- res['success'] = True
339
- except Exception as e:
340
- res['success'] = False
341
- res['note'] += f"; fatal: {e}"
342
-
343
- print('RESULT:' + json.dumps(res))
344
- `.trim();
345
- const pyResp = await this.bridge.executePython(py);
346
- const interpreted = interpretStandardResult(pyResp, {
347
- successMessage: `Painted foliage for '${foliageType}'`,
348
- failureMessage: 'Paint foliage failed'
349
- });
350
- if (!interpreted.success) {
110
+ if (!this.automationBridge) {
111
+ throw new Error('Automation Bridge not available. Foliage operations require plugin support.');
112
+ }
113
+ try {
114
+ const typePath = foliageType.includes('/') ? foliageType : `/Game/Foliage/${foliageType}.${foliageType}`;
115
+ const response = await this.automationBridge.sendAutomationRequest('paint_foliage', {
116
+ foliageTypePath: typePath,
117
+ locations: [{ x: pos[0], y: pos[1], z: pos[2] }],
118
+ brushSize: Number.isFinite(params.brushSize) ? params.brushSize : 300,
119
+ paintDensity: params.paintDensity,
120
+ eraseMode: params.eraseMode
121
+ }, {
122
+ timeoutMs: 60000
123
+ });
124
+ if (response.success === false) {
125
+ return {
126
+ success: false,
127
+ error: response.error || response.message || 'Paint foliage failed',
128
+ note: coerceString(response.result?.note)
129
+ };
130
+ }
131
+ const payload = response.result;
132
+ const added = coerceNumber(payload.instancesPlaced) ?? coerceNumber(payload?.count) ?? 0;
133
+ const note = coerceString(payload.note);
134
+ return {
135
+ success: true,
136
+ added,
137
+ note,
138
+ message: `Painted ${added} instances for '${foliageType}' around (${pos[0]}, ${pos[1]}, ${pos[2]})`
139
+ };
140
+ }
141
+ catch (error) {
351
142
  return {
352
143
  success: false,
353
- error: coerceString(interpreted.payload.note) ?? interpreted.error ?? 'Paint foliage failed',
354
- note: coerceString(interpreted.payload.note) ?? bestEffortInterpretedText(interpreted)
144
+ error: `Failed to paint foliage: ${error instanceof Error ? error.message : String(error)}`
355
145
  };
356
146
  }
357
- const payload = interpreted.payload;
358
- const added = coerceNumber(payload.added) ?? 0;
359
- const actor = coerceString(payload.actor);
360
- const component = coerceString(payload.component);
361
- const usedMesh = coerceString(payload.used_mesh);
362
- const note = coerceString(payload.note);
363
- return {
364
- success: true,
365
- added,
366
- actor,
367
- component,
368
- usedMesh,
369
- note,
370
- message: `Painted ${added} instances for '${foliageType}' around (${pos[0]}, ${pos[1]}, ${pos[2]})`
371
- };
372
147
  }
373
- // Create instanced mesh
148
+ async getFoliageInstances(params) {
149
+ if (!this.automationBridge) {
150
+ throw new Error('Automation Bridge not available. Foliage operations require plugin support.');
151
+ }
152
+ try {
153
+ const typePath = params.foliageType ? (params.foliageType.includes('/') ? params.foliageType : `/Game/Foliage/${params.foliageType}.${params.foliageType}`) : undefined;
154
+ const response = await this.automationBridge.sendAutomationRequest('get_foliage_instances', {
155
+ foliageTypePath: typePath
156
+ }, { timeoutMs: 60000 });
157
+ if (response.success === false) {
158
+ return { success: false, error: response.error || response.message || 'Get foliage instances failed' };
159
+ }
160
+ const payload = response.result;
161
+ return {
162
+ success: true,
163
+ count: coerceNumber(payload.count) ?? 0,
164
+ instances: payload.instances ?? [],
165
+ message: 'Foliage instances retrieved'
166
+ };
167
+ }
168
+ catch (error) {
169
+ return { success: false, error: `Failed to get foliage instances: ${error instanceof Error ? error.message : String(error)}` };
170
+ }
171
+ }
172
+ async removeFoliage(params) {
173
+ if (!this.automationBridge) {
174
+ throw new Error('Automation Bridge not available. Foliage operations require plugin support.');
175
+ }
176
+ try {
177
+ const typePath = params.foliageType ? (params.foliageType.includes('/') ? params.foliageType : `/Game/Foliage/${params.foliageType}.${params.foliageType}`) : undefined;
178
+ const response = await this.automationBridge.sendAutomationRequest('remove_foliage', {
179
+ foliageTypePath: typePath,
180
+ removeAll: !!params.removeAll
181
+ }, { timeoutMs: 60000 });
182
+ if (response.success === false) {
183
+ return { success: false, error: response.error || response.message || 'Remove foliage failed' };
184
+ }
185
+ const payload = response.result;
186
+ return {
187
+ success: true,
188
+ instancesRemoved: coerceNumber(payload.instancesRemoved) ?? 0,
189
+ message: 'Foliage removed'
190
+ };
191
+ }
192
+ catch (error) {
193
+ return { success: false, error: `Failed to remove foliage: ${error instanceof Error ? error.message : String(error)}` };
194
+ }
195
+ }
374
196
  async createInstancedMesh(params) {
375
197
  const commands = [];
376
198
  commands.push(`CreateInstancedStaticMesh ${params.name} ${params.meshPath}`);
@@ -388,7 +210,6 @@ print('RESULT:' + json.dumps(res))
388
210
  await this.bridge.executeConsoleCommands(commands);
389
211
  return { success: true, message: `Instanced mesh ${params.name} created with ${params.instances.length} instances` };
390
212
  }
391
- // Set foliage LOD
392
213
  async setFoliageLOD(params) {
393
214
  const commands = [];
394
215
  if (params.lodDistances) {
@@ -400,24 +221,99 @@ print('RESULT:' + json.dumps(res))
400
221
  await this.bridge.executeConsoleCommands(commands);
401
222
  return { success: true, message: 'Foliage LOD settings updated' };
402
223
  }
403
- // Create procedural foliage
224
+ async addFoliage(params) {
225
+ if (params.locations && params.locations.length > 0) {
226
+ if (!this.automationBridge) {
227
+ throw new Error('Automation Bridge not available.');
228
+ }
229
+ const response = await this.automationBridge.sendAutomationRequest('paint_foliage', {
230
+ foliageTypePath: params.foliageType.includes('/') ? params.foliageType : `/Game/Foliage/${params.foliageType}.${params.foliageType}`,
231
+ locations: params.locations,
232
+ brushSize: 0,
233
+ paintDensity: 1,
234
+ eraseMode: false
235
+ });
236
+ if (!response.success) {
237
+ return { success: false, error: response.error || 'Failed to add foliage instances' };
238
+ }
239
+ return { success: true, message: `Added ${params.locations.length} foliage instances` };
240
+ }
241
+ return { success: true, message: 'No locations provided for addFoliage' };
242
+ }
404
243
  async createProceduralFoliage(params) {
405
- const commands = [];
406
- commands.push(`CreateProceduralFoliageVolume ${params.volumeName} ${params.position.join(' ')} ${params.size.join(' ')}`);
407
- for (const type of params.foliageTypes) {
408
- commands.push(`AddProceduralFoliageType ${params.volumeName} ${type}`);
244
+ if (!this.automationBridge) {
245
+ throw new Error('Automation Bridge not available.');
246
+ }
247
+ const volName = params.volumeName || params.name || 'ProceduralFoliageVolume';
248
+ const loc = params.bounds?.location ? [params.bounds.location.x, params.bounds.location.y, params.bounds.location.z] : (params.position || [0, 0, 0]);
249
+ const size = params.bounds?.size ? [params.bounds.size.x, params.bounds.size.y, params.bounds.size.z] : (params.size || [1000, 1000, 100]);
250
+ const foliageTypes = Array.isArray(params.foliageTypes)
251
+ ? params.foliageTypes.map(t => {
252
+ if (typeof t === 'string')
253
+ return { meshPath: t, density: 0.5 };
254
+ return t;
255
+ })
256
+ : [];
257
+ const payload = {
258
+ name: volName,
259
+ bounds: {
260
+ location: { x: loc[0], y: loc[1], z: loc[2] },
261
+ size: { x: size[0], y: size[1], z: size[2] }
262
+ },
263
+ foliageTypes,
264
+ seed: params.seed ?? 42,
265
+ tileSize: params.tileSize ?? 1000
266
+ };
267
+ const response = await this.automationBridge.sendAutomationRequest('create_procedural_foliage', payload);
268
+ if (!response.success) {
269
+ return {
270
+ success: false,
271
+ error: response.error || 'Failed to create procedural foliage'
272
+ };
409
273
  }
410
- if (params.seed !== undefined) {
411
- commands.push(`SetProceduralSeed ${params.volumeName} ${params.seed}`);
274
+ const result = response.result;
275
+ return {
276
+ success: true,
277
+ message: `Procedural foliage volume ${volName} created`,
278
+ details: response,
279
+ volumeActor: result?.volume_actor,
280
+ spawnerPath: result?.spawner_path,
281
+ foliageTypesCount: result?.foliage_types_count
282
+ };
283
+ }
284
+ async addFoliageInstances(params) {
285
+ if (!this.automationBridge) {
286
+ throw new Error('Automation Bridge not available. Foliage instance placement requires plugin support.');
287
+ }
288
+ try {
289
+ const typePath = params.foliageType.includes('/') ? params.foliageType : `/Game/Foliage/${params.foliageType}.${params.foliageType}`;
290
+ const response = await this.automationBridge.sendAutomationRequest('add_foliage_instances', {
291
+ foliageType: typePath,
292
+ transforms: params.transforms
293
+ }, {
294
+ timeoutMs: 120000
295
+ });
296
+ if (response.success === false) {
297
+ return {
298
+ success: false,
299
+ error: response.error || response.message || 'Failed to add foliage instances',
300
+ message: response.message || 'Failed to add foliage instances'
301
+ };
302
+ }
303
+ const result = response.result;
304
+ return {
305
+ success: true,
306
+ message: response.message || `Added ${result?.instances_count || params.transforms.length} foliage instances`,
307
+ instancesCount: result?.instances_count
308
+ };
412
309
  }
413
- if (params.tileSize !== undefined) {
414
- commands.push(`SetProceduralTileSize ${params.volumeName} ${params.tileSize}`);
310
+ catch (error) {
311
+ return {
312
+ success: false,
313
+ error: `Failed to add foliage instances: ${error instanceof Error ? error.message : String(error)}`
314
+ };
415
315
  }
416
- commands.push(`GenerateProceduralFoliage ${params.volumeName}`);
417
- await this.bridge.executeConsoleCommands(commands);
418
- return { success: true, message: `Procedural foliage volume ${params.volumeName} created` };
419
316
  }
420
- // Set foliage collision
421
317
  async setFoliageCollision(params) {
422
318
  const commands = [];
423
319
  if (params.collisionEnabled !== undefined) {
@@ -432,7 +328,6 @@ print('RESULT:' + json.dumps(res))
432
328
  await this.bridge.executeConsoleCommands(commands);
433
329
  return { success: true, message: 'Foliage collision settings updated' };
434
330
  }
435
- // Create grass system
436
331
  async createGrassSystem(params) {
437
332
  const commands = [];
438
333
  commands.push(`CreateGrassSystem ${params.name}`);
@@ -450,12 +345,10 @@ print('RESULT:' + json.dumps(res))
450
345
  await this.bridge.executeConsoleCommands(commands);
451
346
  return { success: true, message: `Grass system ${params.name} created` };
452
347
  }
453
- // Remove foliage instances
454
348
  async removeFoliageInstances(params) {
455
349
  const command = `RemoveFoliageInRadius ${params.foliageType} ${params.position.join(' ')} ${params.radius}`;
456
350
  return this.bridge.executeConsoleCommand(command);
457
351
  }
458
- // Select foliage instances
459
352
  async selectFoliageInstances(params) {
460
353
  let command;
461
354
  if (params.selectAll) {
@@ -469,7 +362,6 @@ print('RESULT:' + json.dumps(res))
469
362
  }
470
363
  return this.bridge.executeConsoleCommand(command);
471
364
  }
472
- // Update foliage instances
473
365
  async updateFoliageInstances(params) {
474
366
  const commands = [];
475
367
  if (params.updateTransforms) {
@@ -482,7 +374,6 @@ print('RESULT:' + json.dumps(res))
482
374
  await this.bridge.executeConsoleCommands(commands);
483
375
  return { success: true, message: 'Foliage instances updated' };
484
376
  }
485
- // Create foliage spawner
486
377
  async createFoliageSpawner(params) {
487
378
  const commands = [];
488
379
  commands.push(`CreateFoliageSpawner ${params.name} ${params.spawnArea}`);
@@ -494,7 +385,6 @@ print('RESULT:' + json.dumps(res))
494
385
  await this.bridge.executeConsoleCommands(commands);
495
386
  return { success: true, message: `Foliage spawner ${params.name} created` };
496
387
  }
497
- // Optimize foliage
498
388
  async optimizeFoliage(params) {
499
389
  const commands = [];
500
390
  if (params.mergeInstances) {
@@ -0,0 +1,3 @@
1
+ import { ITools } from '../../types/tool-interfaces.js';
2
+ export declare function handleActorTools(action: string, args: any, tools: ITools): Promise<any>;
3
+ //# sourceMappingURL=actor-handlers.d.ts.map