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.
- package/.env.example +26 -0
- package/.env.production +38 -7
- package/.eslintrc.json +0 -54
- package/.eslintrc.override.json +8 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +94 -0
- package/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +56 -0
- package/.github/copilot-instructions.md +478 -45
- package/.github/dependabot.yml +19 -0
- package/.github/labeler.yml +24 -0
- package/.github/labels.yml +70 -0
- package/.github/pull_request_template.md +42 -0
- package/.github/release-drafter-config.yml +51 -0
- package/.github/workflows/auto-merge.yml +38 -0
- package/.github/workflows/ci.yml +38 -0
- package/.github/workflows/dependency-review.yml +17 -0
- package/.github/workflows/gemini-issue-triage.yml +172 -0
- package/.github/workflows/greetings.yml +27 -0
- package/.github/workflows/labeler.yml +17 -0
- package/.github/workflows/links.yml +80 -0
- package/.github/workflows/pr-size-labeler.yml +137 -0
- package/.github/workflows/publish-mcp.yml +13 -7
- package/.github/workflows/release-drafter.yml +23 -0
- package/.github/workflows/release.yml +112 -0
- package/.github/workflows/semantic-pull-request.yml +35 -0
- package/.github/workflows/smoke-test.yml +36 -0
- package/.github/workflows/stale.yml +28 -0
- package/CHANGELOG.md +338 -31
- package/CONTRIBUTING.md +140 -0
- package/GEMINI.md +115 -0
- package/Public/Plugin_setup_guide.mp4 +0 -0
- package/README.md +189 -128
- package/claude_desktop_config_example.json +7 -6
- package/dist/automation/bridge.d.ts +50 -0
- package/dist/automation/bridge.js +452 -0
- package/dist/automation/connection-manager.d.ts +23 -0
- package/dist/automation/connection-manager.js +107 -0
- package/dist/automation/handshake.d.ts +11 -0
- package/dist/automation/handshake.js +89 -0
- package/dist/automation/index.d.ts +3 -0
- package/dist/automation/index.js +3 -0
- package/dist/automation/message-handler.d.ts +12 -0
- package/dist/automation/message-handler.js +149 -0
- package/dist/automation/request-tracker.d.ts +25 -0
- package/dist/automation/request-tracker.js +98 -0
- package/dist/automation/types.d.ts +130 -0
- package/dist/automation/types.js +2 -0
- package/dist/cli.js +32 -5
- package/dist/config.d.ts +26 -0
- package/dist/config.js +59 -0
- package/dist/constants.d.ts +16 -0
- package/dist/constants.js +16 -0
- package/dist/graphql/loaders.d.ts +64 -0
- package/dist/graphql/loaders.js +117 -0
- package/dist/graphql/resolvers.d.ts +268 -0
- package/dist/graphql/resolvers.js +746 -0
- package/dist/graphql/schema.d.ts +5 -0
- package/dist/graphql/schema.js +437 -0
- package/dist/graphql/server.d.ts +26 -0
- package/dist/graphql/server.js +117 -0
- package/dist/graphql/types.d.ts +9 -0
- package/dist/graphql/types.js +2 -0
- package/dist/handlers/resource-handlers.d.ts +20 -0
- package/dist/handlers/resource-handlers.js +180 -0
- package/dist/index.d.ts +33 -18
- package/dist/index.js +130 -619
- package/dist/resources/actors.d.ts +17 -12
- package/dist/resources/actors.js +56 -76
- package/dist/resources/assets.d.ts +6 -14
- package/dist/resources/assets.js +115 -147
- package/dist/resources/levels.d.ts +13 -13
- package/dist/resources/levels.js +25 -34
- package/dist/server/resource-registry.d.ts +20 -0
- package/dist/server/resource-registry.js +37 -0
- package/dist/server/tool-registry.d.ts +23 -0
- package/dist/server/tool-registry.js +322 -0
- package/dist/server-setup.d.ts +20 -0
- package/dist/server-setup.js +71 -0
- package/dist/services/health-monitor.d.ts +34 -0
- package/dist/services/health-monitor.js +105 -0
- package/dist/services/metrics-server.d.ts +11 -0
- package/dist/services/metrics-server.js +105 -0
- package/dist/tools/actors.d.ts +163 -9
- package/dist/tools/actors.js +356 -311
- package/dist/tools/animation.d.ts +135 -4
- package/dist/tools/animation.js +510 -411
- package/dist/tools/assets.d.ts +75 -29
- package/dist/tools/assets.js +265 -284
- package/dist/tools/audio.d.ts +102 -42
- package/dist/tools/audio.js +272 -685
- package/dist/tools/base-tool.d.ts +17 -0
- package/dist/tools/base-tool.js +46 -0
- package/dist/tools/behavior-tree.d.ts +94 -0
- package/dist/tools/behavior-tree.js +39 -0
- package/dist/tools/blueprint.d.ts +208 -126
- package/dist/tools/blueprint.js +685 -832
- package/dist/tools/consolidated-tool-definitions.d.ts +5462 -1781
- package/dist/tools/consolidated-tool-definitions.js +829 -496
- package/dist/tools/consolidated-tool-handlers.d.ts +2 -1
- package/dist/tools/consolidated-tool-handlers.js +198 -1027
- package/dist/tools/debug.d.ts +143 -85
- package/dist/tools/debug.js +234 -180
- package/dist/tools/dynamic-handler-registry.d.ts +13 -0
- package/dist/tools/dynamic-handler-registry.js +23 -0
- package/dist/tools/editor.d.ts +30 -83
- package/dist/tools/editor.js +247 -244
- package/dist/tools/engine.d.ts +10 -4
- package/dist/tools/engine.js +13 -5
- package/dist/tools/environment.d.ts +30 -0
- package/dist/tools/environment.js +267 -0
- package/dist/tools/foliage.d.ts +65 -99
- package/dist/tools/foliage.js +221 -331
- package/dist/tools/handlers/actor-handlers.d.ts +3 -0
- package/dist/tools/handlers/actor-handlers.js +227 -0
- package/dist/tools/handlers/animation-handlers.d.ts +3 -0
- package/dist/tools/handlers/animation-handlers.js +185 -0
- package/dist/tools/handlers/argument-helper.d.ts +16 -0
- package/dist/tools/handlers/argument-helper.js +80 -0
- package/dist/tools/handlers/asset-handlers.d.ts +3 -0
- package/dist/tools/handlers/asset-handlers.js +496 -0
- package/dist/tools/handlers/audio-handlers.d.ts +3 -0
- package/dist/tools/handlers/audio-handlers.js +166 -0
- package/dist/tools/handlers/blueprint-handlers.d.ts +4 -0
- package/dist/tools/handlers/blueprint-handlers.js +358 -0
- package/dist/tools/handlers/common-handlers.d.ts +14 -0
- package/dist/tools/handlers/common-handlers.js +56 -0
- package/dist/tools/handlers/editor-handlers.d.ts +3 -0
- package/dist/tools/handlers/editor-handlers.js +119 -0
- package/dist/tools/handlers/effect-handlers.d.ts +3 -0
- package/dist/tools/handlers/effect-handlers.js +171 -0
- package/dist/tools/handlers/environment-handlers.d.ts +3 -0
- package/dist/tools/handlers/environment-handlers.js +170 -0
- package/dist/tools/handlers/graph-handlers.d.ts +3 -0
- package/dist/tools/handlers/graph-handlers.js +90 -0
- package/dist/tools/handlers/input-handlers.d.ts +3 -0
- package/dist/tools/handlers/input-handlers.js +21 -0
- package/dist/tools/handlers/inspect-handlers.d.ts +3 -0
- package/dist/tools/handlers/inspect-handlers.js +383 -0
- package/dist/tools/handlers/level-handlers.d.ts +3 -0
- package/dist/tools/handlers/level-handlers.js +237 -0
- package/dist/tools/handlers/lighting-handlers.d.ts +3 -0
- package/dist/tools/handlers/lighting-handlers.js +144 -0
- package/dist/tools/handlers/performance-handlers.d.ts +3 -0
- package/dist/tools/handlers/performance-handlers.js +130 -0
- package/dist/tools/handlers/pipeline-handlers.d.ts +3 -0
- package/dist/tools/handlers/pipeline-handlers.js +110 -0
- package/dist/tools/handlers/sequence-handlers.d.ts +3 -0
- package/dist/tools/handlers/sequence-handlers.js +376 -0
- package/dist/tools/handlers/system-handlers.d.ts +4 -0
- package/dist/tools/handlers/system-handlers.js +506 -0
- package/dist/tools/input.d.ts +19 -0
- package/dist/tools/input.js +89 -0
- package/dist/tools/introspection.d.ts +103 -40
- package/dist/tools/introspection.js +425 -568
- package/dist/tools/landscape.d.ts +54 -93
- package/dist/tools/landscape.js +284 -409
- package/dist/tools/level.d.ts +66 -27
- package/dist/tools/level.js +647 -675
- package/dist/tools/lighting.d.ts +77 -38
- package/dist/tools/lighting.js +445 -943
- package/dist/tools/logs.d.ts +3 -3
- package/dist/tools/logs.js +5 -57
- package/dist/tools/materials.d.ts +91 -24
- package/dist/tools/materials.js +194 -118
- package/dist/tools/niagara.d.ts +149 -39
- package/dist/tools/niagara.js +267 -182
- package/dist/tools/performance.d.ts +27 -13
- package/dist/tools/performance.js +203 -122
- package/dist/tools/physics.d.ts +32 -77
- package/dist/tools/physics.js +175 -582
- package/dist/tools/property-dictionary.d.ts +13 -0
- package/dist/tools/property-dictionary.js +82 -0
- package/dist/tools/sequence.d.ts +85 -60
- package/dist/tools/sequence.js +208 -747
- package/dist/tools/tool-definition-utils.d.ts +59 -0
- package/dist/tools/tool-definition-utils.js +35 -0
- package/dist/tools/ui.d.ts +64 -34
- package/dist/tools/ui.js +134 -214
- package/dist/types/automation-responses.d.ts +115 -0
- package/dist/types/automation-responses.js +2 -0
- package/dist/types/env.d.ts +0 -3
- package/dist/types/env.js +0 -7
- package/dist/types/responses.d.ts +249 -0
- package/dist/types/responses.js +2 -0
- package/dist/types/tool-interfaces.d.ts +898 -0
- package/dist/types/tool-interfaces.js +2 -0
- package/dist/types/tool-types.d.ts +183 -19
- package/dist/types/tool-types.js +0 -4
- package/dist/unreal-bridge.d.ts +24 -131
- package/dist/unreal-bridge.js +364 -1506
- package/dist/utils/command-validator.d.ts +9 -0
- package/dist/utils/command-validator.js +68 -0
- package/dist/utils/elicitation.d.ts +1 -1
- package/dist/utils/elicitation.js +12 -15
- package/dist/utils/error-handler.d.ts +2 -51
- package/dist/utils/error-handler.js +11 -87
- package/dist/utils/ini-reader.d.ts +3 -0
- package/dist/utils/ini-reader.js +69 -0
- package/dist/utils/logger.js +9 -6
- package/dist/utils/normalize.d.ts +3 -0
- package/dist/utils/normalize.js +56 -0
- package/dist/utils/path-security.d.ts +2 -0
- package/dist/utils/path-security.js +24 -0
- package/dist/utils/response-factory.d.ts +7 -0
- package/dist/utils/response-factory.js +27 -0
- package/dist/utils/response-validator.d.ts +3 -24
- package/dist/utils/response-validator.js +130 -81
- package/dist/utils/result-helpers.d.ts +4 -5
- package/dist/utils/result-helpers.js +15 -16
- package/dist/utils/safe-json.js +5 -11
- package/dist/utils/unreal-command-queue.d.ts +24 -0
- package/dist/utils/unreal-command-queue.js +120 -0
- package/dist/utils/validation.d.ts +0 -40
- package/dist/utils/validation.js +1 -78
- package/dist/wasm/index.d.ts +70 -0
- package/dist/wasm/index.js +535 -0
- package/docs/GraphQL-API.md +888 -0
- package/docs/Migration-Guide-v0.5.0.md +684 -0
- package/docs/Roadmap.md +53 -0
- package/docs/WebAssembly-Integration.md +628 -0
- package/docs/editor-plugin-extension.md +370 -0
- package/docs/handler-mapping.md +242 -0
- package/docs/native-automation-progress.md +128 -0
- package/docs/testing-guide.md +423 -0
- package/mcp-config-example.json +6 -6
- package/package.json +67 -28
- package/plugins/McpAutomationBridge/Config/FilterPlugin.ini +8 -0
- package/plugins/McpAutomationBridge/McpAutomationBridge.uplugin +64 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/McpAutomationBridge.Build.cs +189 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.cpp +22 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeGlobals.h +30 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeHelpers.h +1983 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeModule.cpp +72 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSettings.cpp +46 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridgeSubsystem.cpp +581 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AnimationHandlers.cpp +2394 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetQueryHandlers.cpp +300 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AssetWorkflowHandlers.cpp +2807 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_AudioHandlers.cpp +1087 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BehaviorTreeHandlers.cpp +488 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.cpp +643 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintCreationHandlers.h +31 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintGraphHandlers.cpp +1184 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers.cpp +5652 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_BlueprintHandlers_List.cpp +152 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ControlHandlers.cpp +2614 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_DebugHandlers.cpp +42 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EditorFunctionHandlers.cpp +1237 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EffectHandlers.cpp +1701 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_EnvironmentHandlers.cpp +2145 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_FoliageHandlers.cpp +954 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InputHandlers.cpp +209 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_InsightsHandlers.cpp +41 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LandscapeHandlers.cpp +1164 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LevelHandlers.cpp +762 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LightingHandlers.cpp +634 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_LogHandlers.cpp +136 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_MaterialGraphHandlers.cpp +494 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraGraphHandlers.cpp +278 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_NiagaraHandlers.cpp +625 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PerformanceHandlers.cpp +401 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PipelineHandlers.cpp +67 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_ProcessRequest.cpp +735 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_PropertyHandlers.cpp +2634 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_RenderHandlers.cpp +189 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.cpp +917 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SCSHandlers.h +39 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequenceHandlers.cpp +2670 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_SequencerHandlers.cpp +519 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_TestHandlers.cpp +38 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_UiHandlers.cpp +668 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpAutomationBridge_WorldPartitionHandlers.cpp +346 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.cpp +1330 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpBridgeWebSocket.h +149 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Private/McpConnectionManager.cpp +783 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSettings.h +115 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpAutomationBridgeSubsystem.h +796 -0
- package/plugins/McpAutomationBridge/Source/McpAutomationBridge/Public/McpConnectionManager.h +117 -0
- package/scripts/check-unreal-connection.mjs +19 -0
- package/scripts/clean-tmp.js +23 -0
- package/scripts/patch-wasm.js +26 -0
- package/scripts/run-all-tests.mjs +136 -0
- package/scripts/smoke-test.ts +94 -0
- package/scripts/sync-mcp-plugin.js +143 -0
- package/scripts/test-no-plugin-alternates.mjs +113 -0
- package/scripts/validate-server.js +46 -0
- package/scripts/verify-automation-bridge.js +200 -0
- package/server.json +58 -21
- package/src/automation/bridge.ts +558 -0
- package/src/automation/connection-manager.ts +130 -0
- package/src/automation/handshake.ts +99 -0
- package/src/automation/index.ts +2 -0
- package/src/automation/message-handler.ts +167 -0
- package/src/automation/request-tracker.ts +123 -0
- package/src/automation/types.ts +107 -0
- package/src/cli.ts +33 -6
- package/src/config.ts +73 -0
- package/src/constants.ts +19 -0
- package/src/graphql/loaders.ts +244 -0
- package/src/graphql/resolvers.ts +1008 -0
- package/src/graphql/schema.ts +452 -0
- package/src/graphql/server.ts +156 -0
- package/src/graphql/types.ts +10 -0
- package/src/handlers/resource-handlers.ts +186 -0
- package/src/index.ts +166 -664
- package/src/resources/actors.ts +58 -76
- package/src/resources/assets.ts +148 -134
- package/src/resources/levels.ts +28 -33
- package/src/server/resource-registry.ts +47 -0
- package/src/server/tool-registry.ts +354 -0
- package/src/server-setup.ts +114 -0
- package/src/services/health-monitor.ts +132 -0
- package/src/services/metrics-server.ts +142 -0
- package/src/tools/actors.ts +426 -323
- package/src/tools/animation.ts +672 -461
- package/src/tools/assets.ts +364 -289
- package/src/tools/audio.ts +323 -766
- package/src/tools/base-tool.ts +52 -0
- package/src/tools/behavior-tree.ts +45 -0
- package/src/tools/blueprint.ts +792 -970
- package/src/tools/consolidated-tool-definitions.ts +993 -515
- package/src/tools/consolidated-tool-handlers.ts +258 -1146
- package/src/tools/debug.ts +292 -187
- package/src/tools/dynamic-handler-registry.ts +33 -0
- package/src/tools/editor.ts +329 -253
- package/src/tools/engine.ts +14 -3
- package/src/tools/environment.ts +281 -0
- package/src/tools/foliage.ts +330 -392
- package/src/tools/handlers/actor-handlers.ts +265 -0
- package/src/tools/handlers/animation-handlers.ts +237 -0
- package/src/tools/handlers/argument-helper.ts +142 -0
- package/src/tools/handlers/asset-handlers.ts +532 -0
- package/src/tools/handlers/audio-handlers.ts +194 -0
- package/src/tools/handlers/blueprint-handlers.ts +380 -0
- package/src/tools/handlers/common-handlers.ts +87 -0
- package/src/tools/handlers/editor-handlers.ts +123 -0
- package/src/tools/handlers/effect-handlers.ts +220 -0
- package/src/tools/handlers/environment-handlers.ts +183 -0
- package/src/tools/handlers/graph-handlers.ts +116 -0
- package/src/tools/handlers/input-handlers.ts +28 -0
- package/src/tools/handlers/inspect-handlers.ts +450 -0
- package/src/tools/handlers/level-handlers.ts +252 -0
- package/src/tools/handlers/lighting-handlers.ts +147 -0
- package/src/tools/handlers/performance-handlers.ts +132 -0
- package/src/tools/handlers/pipeline-handlers.ts +127 -0
- package/src/tools/handlers/sequence-handlers.ts +415 -0
- package/src/tools/handlers/system-handlers.ts +564 -0
- package/src/tools/input.ts +101 -0
- package/src/tools/introspection.ts +493 -584
- package/src/tools/landscape.ts +418 -507
- package/src/tools/level.ts +786 -708
- package/src/tools/lighting.ts +588 -984
- package/src/tools/logs.ts +9 -57
- package/src/tools/materials.ts +237 -121
- package/src/tools/niagara.ts +335 -168
- package/src/tools/performance.ts +320 -169
- package/src/tools/physics.ts +274 -613
- package/src/tools/property-dictionary.ts +98 -0
- package/src/tools/sequence.ts +276 -820
- package/src/tools/tool-definition-utils.ts +35 -0
- package/src/tools/ui.ts +205 -283
- package/src/types/automation-responses.ts +119 -0
- package/src/types/env.ts +0 -10
- package/src/types/responses.ts +355 -0
- package/src/types/tool-interfaces.ts +250 -0
- package/src/types/tool-types.ts +243 -21
- package/src/unreal-bridge.ts +460 -1550
- package/src/utils/command-validator.ts +76 -0
- package/src/utils/elicitation.ts +10 -7
- package/src/utils/error-handler.ts +14 -90
- package/src/utils/ini-reader.ts +86 -0
- package/src/utils/logger.ts +8 -3
- package/src/utils/normalize.test.ts +162 -0
- package/src/utils/normalize.ts +60 -0
- package/src/utils/path-security.ts +43 -0
- package/src/utils/response-factory.ts +44 -0
- package/src/utils/response-validator.ts +176 -56
- package/src/utils/result-helpers.ts +21 -19
- package/src/utils/safe-json.test.ts +90 -0
- package/src/utils/safe-json.ts +14 -11
- package/src/utils/unreal-command-queue.ts +152 -0
- package/src/utils/validation.test.ts +184 -0
- package/src/utils/validation.ts +4 -1
- package/src/wasm/index.ts +838 -0
- package/test-server.mjs +100 -0
- package/tests/run-unreal-tool-tests.mjs +242 -14
- package/tests/test-animation.mjs +369 -0
- package/tests/test-asset-advanced.mjs +82 -0
- package/tests/test-asset-errors.mjs +35 -0
- package/tests/test-asset-graph.mjs +311 -0
- package/tests/test-audio.mjs +417 -0
- package/tests/test-automation-timeouts.mjs +98 -0
- package/tests/test-behavior-tree.mjs +444 -0
- package/tests/test-blueprint-graph.mjs +410 -0
- package/tests/test-blueprint.mjs +577 -0
- package/tests/test-client-mode.mjs +86 -0
- package/tests/test-console-command.mjs +56 -0
- package/tests/test-control-actor.mjs +425 -0
- package/tests/test-control-editor.mjs +112 -0
- package/tests/test-graphql.mjs +372 -0
- package/tests/test-input.mjs +349 -0
- package/tests/test-inspect.mjs +302 -0
- package/tests/test-landscape.mjs +316 -0
- package/tests/test-lighting.mjs +428 -0
- package/tests/test-manage-asset.mjs +438 -0
- package/tests/test-manage-level.mjs +89 -0
- package/tests/test-materials.mjs +356 -0
- package/tests/test-niagara.mjs +185 -0
- package/tests/test-no-inline-python.mjs +122 -0
- package/tests/test-performance.mjs +539 -0
- package/tests/test-plugin-handshake.mjs +82 -0
- package/tests/test-runner.mjs +933 -0
- package/tests/test-sequence.mjs +104 -0
- package/tests/test-system.mjs +96 -0
- package/tests/test-wasm.mjs +283 -0
- package/tests/test-world-partition.mjs +215 -0
- package/tsconfig.json +3 -3
- package/vitest.config.ts +35 -0
- package/wasm/Cargo.lock +363 -0
- package/wasm/Cargo.toml +42 -0
- package/wasm/LICENSE +21 -0
- package/wasm/README.md +253 -0
- package/wasm/src/dependency_resolver.rs +377 -0
- package/wasm/src/lib.rs +153 -0
- package/wasm/src/property_parser.rs +271 -0
- package/wasm/src/transform_math.rs +396 -0
- package/wasm/tests/integration.rs +109 -0
- package/.github/workflows/smithery-build.yml +0 -29
- package/dist/prompts/index.d.ts +0 -21
- package/dist/prompts/index.js +0 -217
- package/dist/tools/build_environment_advanced.d.ts +0 -65
- package/dist/tools/build_environment_advanced.js +0 -633
- package/dist/tools/rc.d.ts +0 -110
- package/dist/tools/rc.js +0 -437
- package/dist/tools/visual.d.ts +0 -40
- package/dist/tools/visual.js +0 -282
- package/dist/utils/http.d.ts +0 -6
- package/dist/utils/http.js +0 -151
- package/dist/utils/python-output.d.ts +0 -18
- package/dist/utils/python-output.js +0 -290
- package/dist/utils/python.d.ts +0 -2
- package/dist/utils/python.js +0 -4
- package/dist/utils/stdio-redirect.d.ts +0 -2
- package/dist/utils/stdio-redirect.js +0 -20
- package/docs/unreal-tool-test-cases.md +0 -574
- package/smithery.yaml +0 -29
- package/src/prompts/index.ts +0 -249
- package/src/tools/build_environment_advanced.ts +0 -732
- package/src/tools/rc.ts +0 -515
- package/src/tools/visual.ts +0 -281
- package/src/utils/http.ts +0 -187
- package/src/utils/python-output.ts +0 -351
- package/src/utils/python.ts +0 -3
- package/src/utils/stdio-redirect.ts +0 -18
package/src/tools/performance.ts
CHANGED
|
@@ -1,17 +1,39 @@
|
|
|
1
1
|
// Performance tools for Unreal Engine
|
|
2
2
|
import { UnrealBridge } from '../unreal-bridge.js';
|
|
3
|
-
import {
|
|
3
|
+
import { AutomationBridge } from '../automation/index.js';
|
|
4
|
+
import { Logger } from '../utils/logger.js';
|
|
4
5
|
|
|
5
6
|
export class PerformanceTools {
|
|
6
|
-
|
|
7
|
+
private log = new Logger('PerformanceTools');
|
|
8
|
+
private automationBridge?: AutomationBridge;
|
|
9
|
+
|
|
10
|
+
constructor(private bridge: UnrealBridge, automationBridge?: AutomationBridge) {
|
|
11
|
+
this.automationBridge = automationBridge;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
setAutomationBridge(automationBridge?: AutomationBridge) {
|
|
15
|
+
this.automationBridge = automationBridge;
|
|
16
|
+
}
|
|
7
17
|
|
|
8
18
|
// Start profiling
|
|
9
19
|
async startProfiling(params: {
|
|
10
20
|
type: 'CPU' | 'GPU' | 'Memory' | 'RenderThread' | 'GameThread' | 'All';
|
|
11
21
|
duration?: number;
|
|
12
22
|
}) {
|
|
13
|
-
|
|
14
|
-
|
|
23
|
+
if (this.automationBridge) {
|
|
24
|
+
try {
|
|
25
|
+
const response = await this.automationBridge.sendAutomationRequest('start_profiling', {
|
|
26
|
+
type: params.type,
|
|
27
|
+
duration: params.duration
|
|
28
|
+
});
|
|
29
|
+
if (response.success) return { success: true, message: `${params.type} profiling started (bridge)` };
|
|
30
|
+
} catch (_e) {
|
|
31
|
+
// Fallback
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const commands: string[] = [];
|
|
36
|
+
|
|
15
37
|
switch (params.type) {
|
|
16
38
|
case 'CPU':
|
|
17
39
|
commands.push('stat startfile');
|
|
@@ -34,25 +56,34 @@ export class PerformanceTools {
|
|
|
34
56
|
commands.push('stat memory');
|
|
35
57
|
break;
|
|
36
58
|
}
|
|
37
|
-
|
|
59
|
+
|
|
38
60
|
if (params.duration) {
|
|
39
61
|
commands.push(`stat stopfile ${params.duration}`);
|
|
40
62
|
}
|
|
41
|
-
|
|
63
|
+
|
|
42
64
|
await this.bridge.executeConsoleCommands(commands);
|
|
43
|
-
|
|
65
|
+
|
|
44
66
|
return { success: true, message: `${params.type} profiling started` };
|
|
45
67
|
}
|
|
46
68
|
|
|
47
69
|
// Stop profiling
|
|
48
70
|
async stopProfiling() {
|
|
71
|
+
if (this.automationBridge) {
|
|
72
|
+
try {
|
|
73
|
+
const response = await this.automationBridge.sendAutomationRequest('stop_profiling', {});
|
|
74
|
+
if (response.success) return { success: true, message: 'Profiling stopped (bridge)' };
|
|
75
|
+
} catch (_e) {
|
|
76
|
+
// Fallback
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
49
80
|
const commands = [
|
|
50
81
|
'stat stopfile',
|
|
51
82
|
'stat none'
|
|
52
83
|
];
|
|
53
|
-
|
|
84
|
+
|
|
54
85
|
await this.bridge.executeConsoleCommands(commands);
|
|
55
|
-
|
|
86
|
+
|
|
56
87
|
return { success: true, message: 'Profiling stopped' };
|
|
57
88
|
}
|
|
58
89
|
|
|
@@ -62,27 +93,43 @@ export class PerformanceTools {
|
|
|
62
93
|
verbose?: boolean;
|
|
63
94
|
}) {
|
|
64
95
|
const startTime = Date.now();
|
|
65
|
-
|
|
66
|
-
|
|
96
|
+
this.log.debug('Starting showFPS with params:', params);
|
|
97
|
+
|
|
98
|
+
if (this.automationBridge) {
|
|
99
|
+
try {
|
|
100
|
+
const response = await this.automationBridge.sendAutomationRequest('show_fps', {
|
|
101
|
+
enabled: params.enabled,
|
|
102
|
+
verbose: params.verbose
|
|
103
|
+
});
|
|
104
|
+
if (response.success) return {
|
|
105
|
+
success: true,
|
|
106
|
+
message: params.enabled ? 'FPS display enabled (bridge)' : 'FPS display disabled (bridge)',
|
|
107
|
+
fpsVisible: params.enabled
|
|
108
|
+
};
|
|
109
|
+
} catch (_e) {
|
|
110
|
+
// Fallback
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
67
114
|
try {
|
|
68
115
|
// Use stat fps as requested - shows FPS counter
|
|
69
116
|
// For more detailed timing info, use 'stat unit' instead
|
|
70
|
-
const command = params.enabled
|
|
117
|
+
const command = params.enabled
|
|
71
118
|
? (params.verbose ? 'stat unit' : 'stat fps')
|
|
72
119
|
: 'stat none';
|
|
73
|
-
|
|
74
|
-
|
|
120
|
+
|
|
121
|
+
this.log.debug(`Executing command: ${command}`);
|
|
75
122
|
await this.bridge.executeConsoleCommand(command);
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
success: true,
|
|
123
|
+
this.log.debug(`Command completed in ${Date.now() - startTime}ms`);
|
|
124
|
+
return {
|
|
125
|
+
success: true,
|
|
79
126
|
message: params.enabled ? 'FPS display enabled' : 'FPS display disabled',
|
|
80
127
|
fpsVisible: params.enabled,
|
|
81
128
|
command: command
|
|
82
129
|
};
|
|
83
130
|
} catch (error) {
|
|
84
|
-
return {
|
|
85
|
-
success: false,
|
|
131
|
+
return {
|
|
132
|
+
success: false,
|
|
86
133
|
error: `Failed to ${params.enabled ? 'enable' : 'disable'} FPS display: ${error}`,
|
|
87
134
|
fpsVisible: false
|
|
88
135
|
};
|
|
@@ -94,10 +141,22 @@ export class PerformanceTools {
|
|
|
94
141
|
category: 'Unit' | 'FPS' | 'Memory' | 'Game' | 'Slate' | 'Engine' | 'RHI' | 'Streaming' | 'SceneRendering' | 'Physics' | 'Navigation' | 'Particles' | 'Audio';
|
|
95
142
|
enabled: boolean;
|
|
96
143
|
}) {
|
|
97
|
-
|
|
144
|
+
if (this.automationBridge) {
|
|
145
|
+
try {
|
|
146
|
+
const response = await this.automationBridge.sendAutomationRequest('show_stats', {
|
|
147
|
+
category: params.category,
|
|
148
|
+
enabled: params.enabled
|
|
149
|
+
});
|
|
150
|
+
if (response.success) return { success: true, message: `Stat '${params.category}' configured (bridge)` };
|
|
151
|
+
} catch (_e) {
|
|
152
|
+
// Fallback
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const command = params.enabled
|
|
98
157
|
? `stat ${params.category.toLowerCase()}`
|
|
99
158
|
: 'stat none';
|
|
100
|
-
|
|
159
|
+
|
|
101
160
|
return this.bridge.executeConsoleCommand(command);
|
|
102
161
|
}
|
|
103
162
|
|
|
@@ -106,6 +165,18 @@ export class PerformanceTools {
|
|
|
106
165
|
category: 'ViewDistance' | 'AntiAliasing' | 'PostProcessing' | 'PostProcess' | 'Shadows' | 'GlobalIllumination' | 'Reflections' | 'Textures' | 'Effects' | 'Foliage' | 'Shading';
|
|
107
166
|
level: 0 | 1 | 2 | 3 | 4; // 0=Low, 1=Medium, 2=High, 3=Epic, 4=Cinematic
|
|
108
167
|
}) {
|
|
168
|
+
if (this.automationBridge) {
|
|
169
|
+
try {
|
|
170
|
+
const response = await this.automationBridge.sendAutomationRequest('set_scalability', {
|
|
171
|
+
category: params.category,
|
|
172
|
+
level: params.level
|
|
173
|
+
});
|
|
174
|
+
if (response.success) return { success: true, message: `${params.category} quality set to level ${params.level} (bridge)` };
|
|
175
|
+
} catch (_e) {
|
|
176
|
+
// Fallback
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
109
180
|
// Map incoming category to the base name expected by "sg.<Base>Quality"
|
|
110
181
|
// Note: Several CVars use singular form (Shadow/Texture/Reflection)
|
|
111
182
|
const categoryBaseMap: Record<string, string> = {
|
|
@@ -130,115 +201,60 @@ export class PerformanceTools {
|
|
|
130
201
|
}
|
|
131
202
|
|
|
132
203
|
const base = categoryBaseMap[params.category] || params.category;
|
|
133
|
-
|
|
204
|
+
|
|
134
205
|
// Use direct console command to set with highest priority (SetByConsole)
|
|
135
206
|
// This avoids conflicts with the scalability system
|
|
136
207
|
const setCommand = `sg.${base}Quality ${requestedLevel}`;
|
|
137
|
-
|
|
208
|
+
|
|
138
209
|
// Apply the console command directly
|
|
139
210
|
await this.bridge.executeConsoleCommand(setCommand);
|
|
140
|
-
|
|
141
|
-
// Skip GameUserSettings entirely to avoid any scalability triggers
|
|
142
|
-
// Console command already applied with correct priority
|
|
143
|
-
/* eslint-disable no-useless-escape */
|
|
144
|
-
const py = `
|
|
145
|
-
import unreal, json
|
|
146
|
-
result = {'success': True, 'category': '${base}', 'requested': ${requestedLevel}, 'actual': ${requestedLevel}, 'method': 'ConsoleOnly'}
|
|
147
|
-
|
|
148
|
-
# Simply verify the console variable was set correctly
|
|
149
|
-
try:
|
|
150
|
-
# Try to read the console variable directly to verify it was set
|
|
151
|
-
# This doesn't trigger any scalability system
|
|
152
|
-
import sys
|
|
153
|
-
from io import StringIO
|
|
154
|
-
|
|
155
|
-
# Capture console output
|
|
156
|
-
old_stdout = sys.stdout
|
|
157
|
-
sys.stdout = StringIO()
|
|
158
|
-
|
|
159
|
-
# Execute console command to query the value
|
|
160
|
-
try:
|
|
161
|
-
unreal.SystemLibrary.execute_console_command(None, 'sg.${base}Quality', None)
|
|
162
|
-
except:
|
|
163
|
-
pass
|
|
164
|
-
|
|
165
|
-
# Get the output
|
|
166
|
-
console_output = sys.stdout.getvalue()
|
|
167
|
-
sys.stdout = old_stdout
|
|
168
|
-
|
|
169
|
-
# Parse the output to get the actual value
|
|
170
|
-
if 'sg.${base}Quality' in console_output:
|
|
171
|
-
# Extract the value from output like 'sg.ShadowQuality = "3"'
|
|
172
|
-
import re
|
|
173
|
-
match = re.search(r'sg\.${base}Quality\\s*=\\s*"(\\d+)"', console_output)
|
|
174
|
-
if match:
|
|
175
|
-
result['actual'] = int(match.group(1))
|
|
176
|
-
result['verified'] = True
|
|
177
|
-
|
|
178
|
-
result['method'] = 'ConsoleOnly'
|
|
179
|
-
except Exception as e:
|
|
180
|
-
# Even on error, the console command was applied
|
|
181
|
-
result['method'] = 'ConsoleOnly'
|
|
182
|
-
result['note'] = str(e)
|
|
183
|
-
|
|
184
|
-
print('RESULT:' + json.dumps(result))
|
|
185
|
-
`.trim();
|
|
186
|
-
/* eslint-enable no-useless-escape */
|
|
187
|
-
|
|
188
|
-
// Always try to apply through Python for consistency
|
|
189
|
-
try {
|
|
190
|
-
const pyResp = await this.bridge.executePython(py);
|
|
191
|
-
const interpreted = interpretStandardResult(pyResp, {
|
|
192
|
-
successMessage: `${params.category} quality set to level ${requestedLevel}`,
|
|
193
|
-
failureMessage: `Failed to set ${params.category} quality`
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
if (interpreted.success) {
|
|
197
|
-
const actual = coerceNumber(interpreted.payload.actual) ?? requestedLevel;
|
|
198
|
-
const verified = coerceBoolean(interpreted.payload.success, true) === true && actual === requestedLevel;
|
|
199
|
-
return {
|
|
200
|
-
success: true,
|
|
201
|
-
message: interpreted.message,
|
|
202
|
-
verified,
|
|
203
|
-
readback: actual,
|
|
204
|
-
method: (interpreted.payload.method as string) || 'ConsoleOnly'
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
} catch {
|
|
208
|
-
// Ignore Python errors and fall through
|
|
209
|
-
}
|
|
210
211
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
success: true,
|
|
212
|
+
return {
|
|
213
|
+
success: true,
|
|
214
214
|
message: `${params.category} quality set to level ${requestedLevel}`,
|
|
215
|
-
method: '
|
|
215
|
+
method: 'Console'
|
|
216
216
|
};
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
// Set resolution scale
|
|
220
220
|
async setResolutionScale(params: {
|
|
221
|
-
scale: number; // 0.
|
|
221
|
+
scale: number; // Accepts both percentage (10-200) and multiplier (0.1-2.0)
|
|
222
222
|
}) {
|
|
223
223
|
// Validate input
|
|
224
224
|
if (params.scale === undefined || params.scale === null || isNaN(params.scale)) {
|
|
225
225
|
return { success: false, error: 'Invalid scale parameter' };
|
|
226
226
|
}
|
|
227
|
-
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
227
|
+
|
|
228
|
+
// Intelligently detect if scale is a percentage (10-200) or multiplier (0.1-2.0)
|
|
229
|
+
// If scale >= 10, assume it's already a percentage value
|
|
230
|
+
let percentage: number;
|
|
231
|
+
if (params.scale >= 10) {
|
|
232
|
+
// User passed percentage directly (e.g., 100 for 100%)
|
|
233
|
+
percentage = Math.round(params.scale);
|
|
234
|
+
} else {
|
|
235
|
+
// User passed multiplier (e.g., 1.0 for 100%)
|
|
236
|
+
percentage = Math.round(params.scale * 100);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Clamp to Unreal's valid range (10-200%)
|
|
234
240
|
const finalPercentage = Math.max(10, Math.min(200, percentage));
|
|
235
|
-
|
|
241
|
+
|
|
242
|
+
if (this.automationBridge) {
|
|
243
|
+
try {
|
|
244
|
+
const response = await this.automationBridge.sendAutomationRequest('set_resolution_scale', { scale: finalPercentage });
|
|
245
|
+
|
|
246
|
+
if (response.success) return { success: true, message: `Resolution scale set to ${finalPercentage}% (bridge)`, actualScale: finalPercentage / 100 };
|
|
247
|
+
} catch (_e) {
|
|
248
|
+
// Fallback
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
236
252
|
const command = `r.ScreenPercentage ${finalPercentage}`;
|
|
237
|
-
|
|
253
|
+
|
|
238
254
|
try {
|
|
239
255
|
await this.bridge.executeConsoleCommand(command);
|
|
240
|
-
return {
|
|
241
|
-
success: true,
|
|
256
|
+
return {
|
|
257
|
+
success: true,
|
|
242
258
|
message: `Resolution scale set to ${finalPercentage}%`,
|
|
243
259
|
actualScale: finalPercentage / 100
|
|
244
260
|
};
|
|
@@ -251,6 +267,14 @@ print('RESULT:' + json.dumps(result))
|
|
|
251
267
|
async setVSync(params: {
|
|
252
268
|
enabled: boolean;
|
|
253
269
|
}) {
|
|
270
|
+
if (this.automationBridge) {
|
|
271
|
+
try {
|
|
272
|
+
const response = await this.automationBridge.sendAutomationRequest('set_vsync', { enabled: params.enabled });
|
|
273
|
+
if (response.success) return { success: true, message: 'VSync configured (bridge)' };
|
|
274
|
+
} catch (_e) {
|
|
275
|
+
// Fallback
|
|
276
|
+
}
|
|
277
|
+
}
|
|
254
278
|
const command = `r.VSync ${params.enabled ? 1 : 0}`;
|
|
255
279
|
return this.bridge.executeConsoleCommand(command);
|
|
256
280
|
}
|
|
@@ -259,6 +283,14 @@ print('RESULT:' + json.dumps(result))
|
|
|
259
283
|
async setFrameRateLimit(params: {
|
|
260
284
|
maxFPS: number; // 0 for unlimited
|
|
261
285
|
}) {
|
|
286
|
+
if (this.automationBridge) {
|
|
287
|
+
try {
|
|
288
|
+
const response = await this.automationBridge.sendAutomationRequest('set_frame_rate_limit', { maxFPS: params.maxFPS });
|
|
289
|
+
if (response.success) return { success: true, message: 'Max FPS set (bridge)' };
|
|
290
|
+
} catch (_e) {
|
|
291
|
+
// Fallback
|
|
292
|
+
}
|
|
293
|
+
}
|
|
262
294
|
const command = `t.MaxFPS ${params.maxFPS}`;
|
|
263
295
|
return this.bridge.executeConsoleCommand(command);
|
|
264
296
|
}
|
|
@@ -267,6 +299,13 @@ print('RESULT:' + json.dumps(result))
|
|
|
267
299
|
async enableGPUTiming(params: {
|
|
268
300
|
enabled: boolean;
|
|
269
301
|
}) {
|
|
302
|
+
// Note: C++ handler doesn't seem to have explicit 'enable_gpu_timing' in the list I saw earlier?
|
|
303
|
+
// Checking McpAutomationBridge_PerformanceHandlers.cpp content provided:
|
|
304
|
+
// It has: generate_memory_report, start/stop_profiling, show_fps, show_stats, set_scalability, set_resolution_scale, set_vsync, set_frame_rate_limit, configure_nanite, configure_lod.
|
|
305
|
+
// IT DOES NOT HAVE enable_gpu_timing.
|
|
306
|
+
// So we stick to console command for this one, or add it to C++ later.
|
|
307
|
+
// I will NOT add bridge call here to avoid failure since I know it's missing.
|
|
308
|
+
|
|
270
309
|
const command = `r.GPUStatsEnabled ${params.enabled ? 1 : 0}`;
|
|
271
310
|
return this.bridge.executeConsoleCommand(command);
|
|
272
311
|
}
|
|
@@ -276,20 +315,41 @@ print('RESULT:' + json.dumps(result))
|
|
|
276
315
|
detailed?: boolean;
|
|
277
316
|
outputPath?: string;
|
|
278
317
|
}) {
|
|
279
|
-
|
|
280
|
-
|
|
318
|
+
// If output path is specified, use Automation Bridge for file writing
|
|
319
|
+
if (this.automationBridge) {
|
|
320
|
+
try {
|
|
321
|
+
const response = await this.automationBridge.sendAutomationRequest('generate_memory_report', {
|
|
322
|
+
detailed: params.detailed ?? false,
|
|
323
|
+
outputPath: params.outputPath
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// Even if no output path, bridge can run the report
|
|
327
|
+
if (response.success) {
|
|
328
|
+
return { success: true, message: response.message || 'Memory report generated' };
|
|
329
|
+
}
|
|
330
|
+
} catch (error) {
|
|
331
|
+
// Fallback only if no output path (since console can't save to file reliably)
|
|
332
|
+
if (params.outputPath) {
|
|
333
|
+
return { success: false, error: `Failed to generate memory report: ${error instanceof Error ? error.message : String(error)}` };
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const commands: string[] = [];
|
|
339
|
+
|
|
281
340
|
if (params.detailed) {
|
|
282
341
|
commands.push('memreport -full');
|
|
283
342
|
} else {
|
|
284
343
|
commands.push('memreport');
|
|
285
344
|
}
|
|
286
|
-
|
|
345
|
+
|
|
346
|
+
// Writing reports to disk via console is not supported
|
|
287
347
|
if (params.outputPath) {
|
|
288
|
-
|
|
348
|
+
throw new Error('Saving memreport to a file requires Automation Bridge support');
|
|
289
349
|
}
|
|
290
|
-
|
|
350
|
+
|
|
291
351
|
await this.bridge.executeConsoleCommands(commands);
|
|
292
|
-
|
|
352
|
+
|
|
293
353
|
return { success: true, message: 'Memory report generated' };
|
|
294
354
|
}
|
|
295
355
|
|
|
@@ -299,20 +359,34 @@ print('RESULT:' + json.dumps(result))
|
|
|
299
359
|
poolSize?: number; // MB
|
|
300
360
|
boostPlayerLocation?: boolean;
|
|
301
361
|
}) {
|
|
302
|
-
|
|
303
|
-
|
|
362
|
+
if (this.automationBridge) {
|
|
363
|
+
try {
|
|
364
|
+
const response = await this.automationBridge.sendAutomationRequest('configure_texture_streaming', {
|
|
365
|
+
enabled: params.enabled,
|
|
366
|
+
poolSize: params.poolSize,
|
|
367
|
+
boostPlayerLocation: params.boostPlayerLocation
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
if (response.success) return { success: true, message: response.message || 'Texture streaming configured (bridge)' };
|
|
371
|
+
} catch (_error) {
|
|
372
|
+
// Fallback
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (params.boostPlayerLocation && !this.automationBridge) {
|
|
377
|
+
throw new Error('Boosting player location for streaming requires Automation Bridge support');
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const commands: string[] = [];
|
|
381
|
+
|
|
304
382
|
commands.push(`r.TextureStreaming ${params.enabled ? 1 : 0}`);
|
|
305
|
-
|
|
383
|
+
|
|
306
384
|
if (params.poolSize !== undefined) {
|
|
307
385
|
commands.push(`r.Streaming.PoolSize ${params.poolSize}`);
|
|
308
386
|
}
|
|
309
|
-
|
|
310
|
-
if (params.boostPlayerLocation !== undefined) {
|
|
311
|
-
commands.push(`r.Streaming.UseFixedPoolSize ${params.boostPlayerLocation ? 1 : 0}`);
|
|
312
|
-
}
|
|
313
|
-
|
|
387
|
+
|
|
314
388
|
await this.bridge.executeConsoleCommands(commands);
|
|
315
|
-
|
|
389
|
+
|
|
316
390
|
return { success: true, message: 'Texture streaming configured' };
|
|
317
391
|
}
|
|
318
392
|
|
|
@@ -322,25 +396,46 @@ print('RESULT:' + json.dumps(result))
|
|
|
322
396
|
lodBias?: number; // skeletal LOD bias (int)
|
|
323
397
|
distanceScale?: number; // distance scale (float) applied to both static and skeletal
|
|
324
398
|
}) {
|
|
325
|
-
|
|
326
|
-
|
|
399
|
+
if (this.automationBridge) {
|
|
400
|
+
try {
|
|
401
|
+
const response = await this.automationBridge.sendAutomationRequest('configure_lod', {
|
|
402
|
+
forceLOD: params.forceLOD,
|
|
403
|
+
lodBias: params.lodBias
|
|
404
|
+
// Note: C++ handler doesn't seem to have explicit 'distanceScale'.
|
|
405
|
+
// We will stick to console for proper implementation of distanceScale
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// If we have distanceScale, we still need to apply it via console as C++ seems to miss it
|
|
409
|
+
if (params.distanceScale !== undefined) {
|
|
410
|
+
await this.bridge.executeConsoleCommand(`r.StaticMeshLODDistanceScale ${params.distanceScale}`);
|
|
411
|
+
await this.bridge.executeConsoleCommand(`r.SkeletalMeshLODDistanceScale ${params.distanceScale}`);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (response.success) return { success: true, message: 'LOD settings configured' };
|
|
415
|
+
} catch (_e) {
|
|
416
|
+
// Fallback
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const commands: string[] = [];
|
|
421
|
+
|
|
327
422
|
if (params.forceLOD !== undefined) {
|
|
328
423
|
commands.push(`r.ForceLOD ${params.forceLOD}`);
|
|
329
424
|
}
|
|
330
|
-
|
|
425
|
+
|
|
331
426
|
if (params.lodBias !== undefined) {
|
|
332
427
|
// Skeletal mesh LOD bias is an integer bias value
|
|
333
428
|
commands.push(`r.SkeletalMeshLODBias ${params.lodBias}`);
|
|
334
429
|
}
|
|
335
|
-
|
|
430
|
+
|
|
336
431
|
if (params.distanceScale !== undefined) {
|
|
337
432
|
// Apply distance scale to both static and skeletal meshes
|
|
338
433
|
commands.push(`r.StaticMeshLODDistanceScale ${params.distanceScale}`);
|
|
339
434
|
commands.push(`r.SkeletalMeshLODDistanceScale ${params.distanceScale}`);
|
|
340
435
|
}
|
|
341
|
-
|
|
436
|
+
|
|
342
437
|
await this.bridge.executeConsoleCommands(commands);
|
|
343
|
-
|
|
438
|
+
|
|
344
439
|
return { success: true, message: 'LOD settings configured' };
|
|
345
440
|
}
|
|
346
441
|
|
|
@@ -352,6 +447,8 @@ print('RESULT:' + json.dumps(result))
|
|
|
352
447
|
maxFPS?: number; // default 60
|
|
353
448
|
hzb?: boolean; // default true
|
|
354
449
|
}) {
|
|
450
|
+
// This is a composite helper, stick to console or individual bridge calls.
|
|
451
|
+
// Console is efficient enough for batch cvar setting.
|
|
355
452
|
const p = {
|
|
356
453
|
distanceScale: params?.distanceScale ?? 1.0,
|
|
357
454
|
skeletalBias: params?.skeletalBias ?? 0,
|
|
@@ -377,23 +474,53 @@ print('RESULT:' + json.dumps(result))
|
|
|
377
474
|
// Draw call optimization
|
|
378
475
|
async optimizeDrawCalls(params: {
|
|
379
476
|
enableInstancing?: boolean;
|
|
380
|
-
|
|
477
|
+
|
|
381
478
|
mergeActors?: boolean;
|
|
479
|
+
actors?: string[];
|
|
382
480
|
}) {
|
|
383
|
-
|
|
384
|
-
|
|
481
|
+
// If merging actors, bridge is required and actors must be provided
|
|
482
|
+
if (params.mergeActors) {
|
|
483
|
+
if (this.automationBridge) {
|
|
484
|
+
try {
|
|
485
|
+
const actors = Array.isArray(params.actors)
|
|
486
|
+
? params.actors.filter((name): name is string => typeof name === 'string' && name.length > 0)
|
|
487
|
+
: undefined;
|
|
488
|
+
|
|
489
|
+
if (!actors || actors.length < 2) {
|
|
490
|
+
return {
|
|
491
|
+
success: false,
|
|
492
|
+
error: 'Merge actors requires an "actors" array with at least 2 valid actor names.'
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const payload: any = {
|
|
497
|
+
enableInstancing: params.enableInstancing,
|
|
498
|
+
mergeActors: params.mergeActors,
|
|
499
|
+
actors: actors
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
const response = await this.automationBridge.sendAutomationRequest('merge_actors', payload);
|
|
503
|
+
|
|
504
|
+
return response.success
|
|
505
|
+
? { success: true, message: response.message || 'Actors merged for optimization' }
|
|
506
|
+
: { success: false, error: response.message || response.error || 'Failed to merge actors' };
|
|
507
|
+
} catch (error) {
|
|
508
|
+
return { success: false, error: `Failed to merge actors: ${error instanceof Error ? error.message : String(error)}` };
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
throw new Error('Actor merging requires Automation Bridge support');
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const commands: string[] = [];
|
|
515
|
+
|
|
385
516
|
if (params.enableInstancing !== undefined) {
|
|
386
517
|
commands.push(`r.MeshDrawCommands.DynamicInstancing ${params.enableInstancing ? 1 : 0}`);
|
|
387
518
|
}
|
|
388
|
-
|
|
519
|
+
|
|
389
520
|
// Avoid using r.RHICmdBypass; it's a low-level debug toggle and not suitable for general batching control
|
|
390
|
-
|
|
391
|
-
if (params.mergeActors) {
|
|
392
|
-
commands.push('MergeActors');
|
|
393
|
-
}
|
|
394
|
-
|
|
521
|
+
|
|
395
522
|
await this.bridge.executeConsoleCommands(commands);
|
|
396
|
-
|
|
523
|
+
|
|
397
524
|
return { success: true, message: 'Draw call optimization configured' };
|
|
398
525
|
}
|
|
399
526
|
|
|
@@ -403,18 +530,18 @@ print('RESULT:' + json.dumps(result))
|
|
|
403
530
|
method?: 'Hardware' | 'Software' | 'Hierarchical';
|
|
404
531
|
freezeRendering?: boolean;
|
|
405
532
|
}) {
|
|
406
|
-
|
|
407
|
-
|
|
533
|
+
const commands: string[] = [];
|
|
534
|
+
|
|
408
535
|
// Enable/disable HZB occlusion (boolean)
|
|
409
536
|
commands.push(`r.HZBOcclusion ${params.enabled ? 1 : 0}`);
|
|
410
|
-
|
|
537
|
+
|
|
411
538
|
// Optional freeze rendering toggle
|
|
412
539
|
if (params.freezeRendering !== undefined) {
|
|
413
540
|
commands.push(`FreezeRendering ${params.freezeRendering ? 1 : 0}`);
|
|
414
541
|
}
|
|
415
|
-
|
|
542
|
+
|
|
416
543
|
await this.bridge.executeConsoleCommands(commands);
|
|
417
|
-
|
|
544
|
+
|
|
418
545
|
return { success: true, message: 'Occlusion culling configured' };
|
|
419
546
|
}
|
|
420
547
|
|
|
@@ -424,22 +551,22 @@ print('RESULT:' + json.dumps(result))
|
|
|
424
551
|
cacheShaders?: boolean;
|
|
425
552
|
reducePermutations?: boolean;
|
|
426
553
|
}) {
|
|
427
|
-
|
|
428
|
-
|
|
554
|
+
const commands: string[] = [];
|
|
555
|
+
|
|
429
556
|
if (params.compileOnDemand !== undefined) {
|
|
430
557
|
commands.push(`r.ShaderDevelopmentMode ${params.compileOnDemand ? 1 : 0}`);
|
|
431
558
|
}
|
|
432
|
-
|
|
559
|
+
|
|
433
560
|
if (params.cacheShaders !== undefined) {
|
|
434
561
|
commands.push(`r.ShaderPipelineCache.Enabled ${params.cacheShaders ? 1 : 0}`);
|
|
435
562
|
}
|
|
436
|
-
|
|
563
|
+
|
|
437
564
|
if (params.reducePermutations) {
|
|
438
565
|
commands.push('RecompileShaders changed');
|
|
439
566
|
}
|
|
440
|
-
|
|
567
|
+
|
|
441
568
|
await this.bridge.executeConsoleCommands(commands);
|
|
442
|
-
|
|
569
|
+
|
|
443
570
|
return { success: true, message: 'Shader optimization configured' };
|
|
444
571
|
}
|
|
445
572
|
|
|
@@ -449,20 +576,44 @@ print('RESULT:' + json.dumps(result))
|
|
|
449
576
|
maxPixelsPerEdge?: number;
|
|
450
577
|
streamingPoolSize?: number;
|
|
451
578
|
}) {
|
|
452
|
-
|
|
453
|
-
|
|
579
|
+
if (this.automationBridge) {
|
|
580
|
+
try {
|
|
581
|
+
const response = await this.automationBridge.sendAutomationRequest('configure_nanite', {
|
|
582
|
+
enabled: params.enabled,
|
|
583
|
+
maxPixelsPerEdge: params.maxPixelsPerEdge,
|
|
584
|
+
streamingPoolSize: params.streamingPoolSize
|
|
585
|
+
});
|
|
586
|
+
// C++ handler snippet only showed `r.Nanite`.
|
|
587
|
+
// Checking snippet: `if (CVar) CVar->Set(bEnabled ? 1 : 0);`
|
|
588
|
+
// It missed maxPixelsPerEdge and streamingPoolSize in the snippet I read.
|
|
589
|
+
// Let's rely on fallback or partial console commands for the extras.
|
|
590
|
+
if (params.maxPixelsPerEdge !== undefined) {
|
|
591
|
+
await this.bridge.executeConsoleCommand(`r.Nanite.MaxPixelsPerEdge ${params.maxPixelsPerEdge}`);
|
|
592
|
+
}
|
|
593
|
+
if (params.streamingPoolSize !== undefined) {
|
|
594
|
+
await this.bridge.executeConsoleCommand(`r.Nanite.StreamingPoolSize ${params.streamingPoolSize}`);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if (response.success) return { success: true, message: 'Nanite configured' };
|
|
598
|
+
} catch (_e) {
|
|
599
|
+
// Fallback
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
const commands: string[] = [];
|
|
604
|
+
|
|
454
605
|
commands.push(`r.Nanite ${params.enabled ? 1 : 0}`);
|
|
455
|
-
|
|
606
|
+
|
|
456
607
|
if (params.maxPixelsPerEdge !== undefined) {
|
|
457
608
|
commands.push(`r.Nanite.MaxPixelsPerEdge ${params.maxPixelsPerEdge}`);
|
|
458
609
|
}
|
|
459
|
-
|
|
610
|
+
|
|
460
611
|
if (params.streamingPoolSize !== undefined) {
|
|
461
612
|
commands.push(`r.Nanite.StreamingPoolSize ${params.streamingPoolSize}`);
|
|
462
613
|
}
|
|
463
|
-
|
|
614
|
+
|
|
464
615
|
await this.bridge.executeConsoleCommands(commands);
|
|
465
|
-
|
|
616
|
+
|
|
466
617
|
return { success: true, message: 'Nanite configured' };
|
|
467
618
|
}
|
|
468
619
|
|
|
@@ -472,20 +623,20 @@ print('RESULT:' + json.dumps(result))
|
|
|
472
623
|
streamingDistance?: number;
|
|
473
624
|
cellSize?: number;
|
|
474
625
|
}) {
|
|
475
|
-
|
|
476
|
-
|
|
626
|
+
const commands: string[] = [];
|
|
627
|
+
|
|
477
628
|
commands.push(`wp.Runtime.EnableStreaming ${params.enabled ? 1 : 0}`);
|
|
478
|
-
|
|
629
|
+
|
|
479
630
|
if (params.streamingDistance !== undefined) {
|
|
480
631
|
commands.push(`wp.Runtime.StreamingDistance ${params.streamingDistance}`);
|
|
481
632
|
}
|
|
482
|
-
|
|
633
|
+
|
|
483
634
|
if (params.cellSize !== undefined) {
|
|
484
635
|
commands.push(`wp.Runtime.CellSize ${params.cellSize}`);
|
|
485
636
|
}
|
|
486
|
-
|
|
637
|
+
|
|
487
638
|
await this.bridge.executeConsoleCommands(commands);
|
|
488
|
-
|
|
639
|
+
|
|
489
640
|
return { success: true, message: 'World Partition configured' };
|
|
490
641
|
}
|
|
491
642
|
|
|
@@ -495,16 +646,16 @@ print('RESULT:' + json.dumps(result))
|
|
|
495
646
|
outputPath?: string;
|
|
496
647
|
}) {
|
|
497
648
|
const duration = params.duration || 60;
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
649
|
+
|
|
650
|
+
// Start recording and GPU profiling
|
|
651
|
+
await this.bridge.executeConsoleCommands(['stat startfile', 'profilegpu']);
|
|
652
|
+
|
|
502
653
|
// Wait for the requested duration
|
|
503
654
|
await new Promise(resolve => setTimeout(resolve, duration * 1000));
|
|
504
|
-
|
|
655
|
+
|
|
505
656
|
// Stop recording and clear stats
|
|
506
657
|
await this.bridge.executeConsoleCommands(['stat stopfile', 'stat none']);
|
|
507
|
-
|
|
658
|
+
|
|
508
659
|
return { success: true, message: `Benchmark completed for ${duration} seconds` };
|
|
509
660
|
}
|
|
510
661
|
}
|