unreal-engine-mcp-server 0.2.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 (155) hide show
  1. package/.dockerignore +57 -0
  2. package/.env.production +25 -0
  3. package/.eslintrc.json +54 -0
  4. package/.github/workflows/publish-mcp.yml +75 -0
  5. package/Dockerfile +54 -0
  6. package/LICENSE +21 -0
  7. package/Public/icon.png +0 -0
  8. package/README.md +209 -0
  9. package/claude_desktop_config_example.json +13 -0
  10. package/dist/cli.d.ts +3 -0
  11. package/dist/cli.js +7 -0
  12. package/dist/index.d.ts +31 -0
  13. package/dist/index.js +484 -0
  14. package/dist/prompts/index.d.ts +14 -0
  15. package/dist/prompts/index.js +38 -0
  16. package/dist/python-utils.d.ts +29 -0
  17. package/dist/python-utils.js +54 -0
  18. package/dist/resources/actors.d.ts +13 -0
  19. package/dist/resources/actors.js +83 -0
  20. package/dist/resources/assets.d.ts +23 -0
  21. package/dist/resources/assets.js +245 -0
  22. package/dist/resources/levels.d.ts +17 -0
  23. package/dist/resources/levels.js +94 -0
  24. package/dist/tools/actors.d.ts +51 -0
  25. package/dist/tools/actors.js +459 -0
  26. package/dist/tools/animation.d.ts +196 -0
  27. package/dist/tools/animation.js +579 -0
  28. package/dist/tools/assets.d.ts +21 -0
  29. package/dist/tools/assets.js +304 -0
  30. package/dist/tools/audio.d.ts +170 -0
  31. package/dist/tools/audio.js +416 -0
  32. package/dist/tools/blueprint.d.ts +144 -0
  33. package/dist/tools/blueprint.js +652 -0
  34. package/dist/tools/build_environment_advanced.d.ts +66 -0
  35. package/dist/tools/build_environment_advanced.js +484 -0
  36. package/dist/tools/consolidated-tool-definitions.d.ts +2598 -0
  37. package/dist/tools/consolidated-tool-definitions.js +607 -0
  38. package/dist/tools/consolidated-tool-handlers.d.ts +2 -0
  39. package/dist/tools/consolidated-tool-handlers.js +1050 -0
  40. package/dist/tools/debug.d.ts +185 -0
  41. package/dist/tools/debug.js +265 -0
  42. package/dist/tools/editor.d.ts +88 -0
  43. package/dist/tools/editor.js +365 -0
  44. package/dist/tools/engine.d.ts +30 -0
  45. package/dist/tools/engine.js +36 -0
  46. package/dist/tools/foliage.d.ts +155 -0
  47. package/dist/tools/foliage.js +525 -0
  48. package/dist/tools/introspection.d.ts +98 -0
  49. package/dist/tools/introspection.js +683 -0
  50. package/dist/tools/landscape.d.ts +158 -0
  51. package/dist/tools/landscape.js +375 -0
  52. package/dist/tools/level.d.ts +110 -0
  53. package/dist/tools/level.js +362 -0
  54. package/dist/tools/lighting.d.ts +159 -0
  55. package/dist/tools/lighting.js +1179 -0
  56. package/dist/tools/materials.d.ts +34 -0
  57. package/dist/tools/materials.js +146 -0
  58. package/dist/tools/niagara.d.ts +145 -0
  59. package/dist/tools/niagara.js +289 -0
  60. package/dist/tools/performance.d.ts +163 -0
  61. package/dist/tools/performance.js +412 -0
  62. package/dist/tools/physics.d.ts +189 -0
  63. package/dist/tools/physics.js +784 -0
  64. package/dist/tools/rc.d.ts +110 -0
  65. package/dist/tools/rc.js +363 -0
  66. package/dist/tools/sequence.d.ts +112 -0
  67. package/dist/tools/sequence.js +675 -0
  68. package/dist/tools/tool-definitions.d.ts +4919 -0
  69. package/dist/tools/tool-definitions.js +891 -0
  70. package/dist/tools/tool-handlers.d.ts +47 -0
  71. package/dist/tools/tool-handlers.js +830 -0
  72. package/dist/tools/ui.d.ts +171 -0
  73. package/dist/tools/ui.js +337 -0
  74. package/dist/tools/visual.d.ts +29 -0
  75. package/dist/tools/visual.js +67 -0
  76. package/dist/types/env.d.ts +10 -0
  77. package/dist/types/env.js +18 -0
  78. package/dist/types/index.d.ts +323 -0
  79. package/dist/types/index.js +28 -0
  80. package/dist/types/tool-types.d.ts +274 -0
  81. package/dist/types/tool-types.js +13 -0
  82. package/dist/unreal-bridge.d.ts +126 -0
  83. package/dist/unreal-bridge.js +992 -0
  84. package/dist/utils/cache-manager.d.ts +64 -0
  85. package/dist/utils/cache-manager.js +176 -0
  86. package/dist/utils/error-handler.d.ts +66 -0
  87. package/dist/utils/error-handler.js +243 -0
  88. package/dist/utils/errors.d.ts +133 -0
  89. package/dist/utils/errors.js +256 -0
  90. package/dist/utils/http.d.ts +26 -0
  91. package/dist/utils/http.js +135 -0
  92. package/dist/utils/logger.d.ts +12 -0
  93. package/dist/utils/logger.js +32 -0
  94. package/dist/utils/normalize.d.ts +17 -0
  95. package/dist/utils/normalize.js +49 -0
  96. package/dist/utils/response-validator.d.ts +34 -0
  97. package/dist/utils/response-validator.js +121 -0
  98. package/dist/utils/safe-json.d.ts +4 -0
  99. package/dist/utils/safe-json.js +97 -0
  100. package/dist/utils/stdio-redirect.d.ts +2 -0
  101. package/dist/utils/stdio-redirect.js +20 -0
  102. package/dist/utils/validation.d.ts +50 -0
  103. package/dist/utils/validation.js +173 -0
  104. package/mcp-config-example.json +14 -0
  105. package/package.json +63 -0
  106. package/server.json +60 -0
  107. package/src/cli.ts +7 -0
  108. package/src/index.ts +543 -0
  109. package/src/prompts/index.ts +51 -0
  110. package/src/python/editor_compat.py +181 -0
  111. package/src/python-utils.ts +57 -0
  112. package/src/resources/actors.ts +92 -0
  113. package/src/resources/assets.ts +251 -0
  114. package/src/resources/levels.ts +83 -0
  115. package/src/tools/actors.ts +480 -0
  116. package/src/tools/animation.ts +713 -0
  117. package/src/tools/assets.ts +305 -0
  118. package/src/tools/audio.ts +548 -0
  119. package/src/tools/blueprint.ts +736 -0
  120. package/src/tools/build_environment_advanced.ts +526 -0
  121. package/src/tools/consolidated-tool-definitions.ts +619 -0
  122. package/src/tools/consolidated-tool-handlers.ts +1093 -0
  123. package/src/tools/debug.ts +368 -0
  124. package/src/tools/editor.ts +360 -0
  125. package/src/tools/engine.ts +32 -0
  126. package/src/tools/foliage.ts +652 -0
  127. package/src/tools/introspection.ts +778 -0
  128. package/src/tools/landscape.ts +523 -0
  129. package/src/tools/level.ts +410 -0
  130. package/src/tools/lighting.ts +1316 -0
  131. package/src/tools/materials.ts +148 -0
  132. package/src/tools/niagara.ts +312 -0
  133. package/src/tools/performance.ts +549 -0
  134. package/src/tools/physics.ts +924 -0
  135. package/src/tools/rc.ts +437 -0
  136. package/src/tools/sequence.ts +791 -0
  137. package/src/tools/tool-definitions.ts +907 -0
  138. package/src/tools/tool-handlers.ts +941 -0
  139. package/src/tools/ui.ts +499 -0
  140. package/src/tools/visual.ts +60 -0
  141. package/src/types/env.ts +27 -0
  142. package/src/types/index.ts +414 -0
  143. package/src/types/tool-types.ts +343 -0
  144. package/src/unreal-bridge.ts +1118 -0
  145. package/src/utils/cache-manager.ts +213 -0
  146. package/src/utils/error-handler.ts +320 -0
  147. package/src/utils/errors.ts +312 -0
  148. package/src/utils/http.ts +184 -0
  149. package/src/utils/logger.ts +30 -0
  150. package/src/utils/normalize.ts +54 -0
  151. package/src/utils/response-validator.ts +145 -0
  152. package/src/utils/safe-json.ts +112 -0
  153. package/src/utils/stdio-redirect.ts +18 -0
  154. package/src/utils/validation.ts +212 -0
  155. package/tsconfig.json +33 -0
@@ -0,0 +1,163 @@
1
+ import { UnrealBridge } from '../unreal-bridge.js';
2
+ export declare class PerformanceTools {
3
+ private bridge;
4
+ constructor(bridge: UnrealBridge);
5
+ private _executeCommand;
6
+ startProfiling(params: {
7
+ type: 'CPU' | 'GPU' | 'Memory' | 'RenderThread' | 'GameThread' | 'All';
8
+ duration?: number;
9
+ }): Promise<{
10
+ success: boolean;
11
+ message: string;
12
+ }>;
13
+ stopProfiling(): Promise<{
14
+ success: boolean;
15
+ message: string;
16
+ }>;
17
+ showFPS(params: {
18
+ enabled: boolean;
19
+ verbose?: boolean;
20
+ }): Promise<{
21
+ success: boolean;
22
+ message: string;
23
+ fpsVisible: boolean;
24
+ command: string;
25
+ error?: undefined;
26
+ } | {
27
+ success: boolean;
28
+ error: string;
29
+ fpsVisible: boolean;
30
+ message?: undefined;
31
+ command?: undefined;
32
+ }>;
33
+ showStats(params: {
34
+ category: 'Unit' | 'FPS' | 'Memory' | 'Game' | 'Slate' | 'Engine' | 'RHI' | 'Streaming' | 'SceneRendering' | 'Physics' | 'Navigation' | 'Particles' | 'Audio';
35
+ enabled: boolean;
36
+ }): Promise<any>;
37
+ setScalability(params: {
38
+ category: 'ViewDistance' | 'AntiAliasing' | 'PostProcessing' | 'PostProcess' | 'Shadows' | 'GlobalIllumination' | 'Reflections' | 'Textures' | 'Effects' | 'Foliage' | 'Shading';
39
+ level: 0 | 1 | 2 | 3 | 4;
40
+ }): Promise<{
41
+ success: boolean;
42
+ message: string;
43
+ verified: any;
44
+ readback: any;
45
+ method: any;
46
+ } | {
47
+ success: boolean;
48
+ message: string;
49
+ method: string;
50
+ verified?: undefined;
51
+ readback?: undefined;
52
+ }>;
53
+ setResolutionScale(params: {
54
+ scale: number;
55
+ }): Promise<{
56
+ success: boolean;
57
+ error: string;
58
+ message?: undefined;
59
+ actualScale?: undefined;
60
+ } | {
61
+ success: boolean;
62
+ message: string;
63
+ actualScale: number;
64
+ error?: undefined;
65
+ }>;
66
+ setVSync(params: {
67
+ enabled: boolean;
68
+ }): Promise<any>;
69
+ setFrameRateLimit(params: {
70
+ maxFPS: number;
71
+ }): Promise<any>;
72
+ enableGPUTiming(params: {
73
+ enabled: boolean;
74
+ }): Promise<any>;
75
+ generateMemoryReport(params: {
76
+ detailed?: boolean;
77
+ outputPath?: string;
78
+ }): Promise<{
79
+ success: boolean;
80
+ message: string;
81
+ }>;
82
+ configureTextureStreaming(params: {
83
+ enabled: boolean;
84
+ poolSize?: number;
85
+ boostPlayerLocation?: boolean;
86
+ }): Promise<{
87
+ success: boolean;
88
+ message: string;
89
+ }>;
90
+ configureLOD(params: {
91
+ forceLOD?: number;
92
+ lodBias?: number;
93
+ distanceScale?: number;
94
+ }): Promise<{
95
+ success: boolean;
96
+ message: string;
97
+ }>;
98
+ applyBaselinePerformanceSettings(params?: {
99
+ distanceScale?: number;
100
+ skeletalBias?: number;
101
+ vsync?: boolean;
102
+ maxFPS?: number;
103
+ hzb?: boolean;
104
+ }): Promise<{
105
+ success: boolean;
106
+ message: string;
107
+ params: {
108
+ distanceScale: number;
109
+ skeletalBias: number;
110
+ vsync: boolean;
111
+ maxFPS: number;
112
+ hzb: boolean;
113
+ };
114
+ }>;
115
+ optimizeDrawCalls(params: {
116
+ enableInstancing?: boolean;
117
+ enableBatching?: boolean;
118
+ mergeActors?: boolean;
119
+ }): Promise<{
120
+ success: boolean;
121
+ message: string;
122
+ }>;
123
+ configureOcclusionCulling(params: {
124
+ enabled: boolean;
125
+ method?: 'Hardware' | 'Software' | 'Hierarchical';
126
+ freezeRendering?: boolean;
127
+ }): Promise<{
128
+ success: boolean;
129
+ message: string;
130
+ }>;
131
+ optimizeShaders(params: {
132
+ compileOnDemand?: boolean;
133
+ cacheShaders?: boolean;
134
+ reducePermutations?: boolean;
135
+ }): Promise<{
136
+ success: boolean;
137
+ message: string;
138
+ }>;
139
+ configureNanite(params: {
140
+ enabled: boolean;
141
+ maxPixelsPerEdge?: number;
142
+ streamingPoolSize?: number;
143
+ }): Promise<{
144
+ success: boolean;
145
+ message: string;
146
+ }>;
147
+ configureWorldPartition(params: {
148
+ enabled: boolean;
149
+ streamingDistance?: number;
150
+ cellSize?: number;
151
+ }): Promise<{
152
+ success: boolean;
153
+ message: string;
154
+ }>;
155
+ runBenchmark(params: {
156
+ duration?: number;
157
+ outputPath?: string;
158
+ }): Promise<{
159
+ success: boolean;
160
+ message: string;
161
+ }>;
162
+ }
163
+ //# sourceMappingURL=performance.d.ts.map
@@ -0,0 +1,412 @@
1
+ export class PerformanceTools {
2
+ bridge;
3
+ constructor(bridge) {
4
+ this.bridge = bridge;
5
+ }
6
+ // Execute console command
7
+ async _executeCommand(command) {
8
+ return this.bridge.httpCall('/remote/object/call', 'PUT', {
9
+ objectPath: '/Script/Engine.Default__KismetSystemLibrary',
10
+ functionName: 'ExecuteConsoleCommand',
11
+ parameters: {
12
+ WorldContextObject: null,
13
+ Command: command,
14
+ SpecificPlayer: null
15
+ },
16
+ generateTransaction: false
17
+ });
18
+ }
19
+ // Start profiling
20
+ async startProfiling(params) {
21
+ const commands = [];
22
+ switch (params.type) {
23
+ case 'CPU':
24
+ commands.push('stat startfile');
25
+ break;
26
+ case 'GPU':
27
+ commands.push('profilegpu');
28
+ break;
29
+ case 'Memory':
30
+ commands.push('stat memory');
31
+ break;
32
+ case 'RenderThread':
33
+ commands.push('stat renderthread');
34
+ break;
35
+ case 'GameThread':
36
+ commands.push('stat game');
37
+ break;
38
+ case 'All':
39
+ commands.push('stat startfile');
40
+ commands.push('profilegpu');
41
+ commands.push('stat memory');
42
+ break;
43
+ }
44
+ if (params.duration) {
45
+ commands.push(`stat stopfile ${params.duration}`);
46
+ }
47
+ for (const cmd of commands) {
48
+ await this.bridge.executeConsoleCommand(cmd);
49
+ }
50
+ return { success: true, message: `${params.type} profiling started` };
51
+ }
52
+ // Stop profiling
53
+ async stopProfiling() {
54
+ const commands = [
55
+ 'stat stopfile',
56
+ 'stat none'
57
+ ];
58
+ for (const cmd of commands) {
59
+ await this.bridge.executeConsoleCommand(cmd);
60
+ }
61
+ return { success: true, message: 'Profiling stopped' };
62
+ }
63
+ // Show FPS
64
+ async showFPS(params) {
65
+ const startTime = Date.now();
66
+ console.log('[PerformanceTools] Starting showFPS with params:', params);
67
+ try {
68
+ // Use stat fps as requested - shows FPS counter
69
+ // For more detailed timing info, use 'stat unit' instead
70
+ const command = params.enabled
71
+ ? (params.verbose ? 'stat unit' : 'stat fps')
72
+ : 'stat none';
73
+ console.log(`[PerformanceTools] Executing command: ${command}`);
74
+ await this.bridge.executeConsoleCommand(command);
75
+ console.log(`[PerformanceTools] Command completed in ${Date.now() - startTime}ms`);
76
+ return {
77
+ success: true,
78
+ message: params.enabled ? 'FPS display enabled' : 'FPS display disabled',
79
+ fpsVisible: params.enabled,
80
+ command: command
81
+ };
82
+ }
83
+ catch (error) {
84
+ return {
85
+ success: false,
86
+ error: `Failed to ${params.enabled ? 'enable' : 'disable'} FPS display: ${error}`,
87
+ fpsVisible: false
88
+ };
89
+ }
90
+ }
91
+ // Show performance stats
92
+ async showStats(params) {
93
+ const command = params.enabled
94
+ ? `stat ${params.category.toLowerCase()}`
95
+ : 'stat none';
96
+ return this.bridge.executeConsoleCommand(command);
97
+ }
98
+ // Set scalability settings using console commands
99
+ async setScalability(params) {
100
+ // Map incoming category to the base name expected by "sg.<Base>Quality"
101
+ // Note: Several CVars use singular form (Shadow/Texture/Reflection)
102
+ const categoryBaseMap = {
103
+ ViewDistance: 'ViewDistance',
104
+ AntiAliasing: 'AntiAliasing',
105
+ PostProcessing: 'PostProcess',
106
+ PostProcess: 'PostProcess',
107
+ Shadows: 'Shadow',
108
+ GlobalIllumination: 'GlobalIllumination',
109
+ Reflections: 'Reflection',
110
+ Textures: 'Texture',
111
+ Effects: 'Effects',
112
+ Foliage: 'Foliage',
113
+ Shading: 'Shading',
114
+ };
115
+ const base = categoryBaseMap[params.category] || params.category;
116
+ // Use direct console command to set with highest priority (SetByConsole)
117
+ // This avoids conflicts with the scalability system
118
+ const setCommand = `sg.${base}Quality ${params.level}`;
119
+ // Apply the console command directly
120
+ await this.bridge.executeConsoleCommand(setCommand);
121
+ // Skip GameUserSettings entirely to avoid any scalability triggers
122
+ // Console command already applied with correct priority
123
+ /* eslint-disable no-useless-escape */
124
+ const py = `
125
+ import unreal, json
126
+ result = {'success': True, 'category': '${base}', 'requested': ${params.level}, 'actual': ${params.level}, 'method': 'ConsoleOnly'}
127
+
128
+ # Simply verify the console variable was set correctly
129
+ try:
130
+ # Try to read the console variable directly to verify it was set
131
+ # This doesn't trigger any scalability system
132
+ import sys
133
+ from io import StringIO
134
+
135
+ # Capture console output
136
+ old_stdout = sys.stdout
137
+ sys.stdout = StringIO()
138
+
139
+ # Execute console command to query the value
140
+ try:
141
+ unreal.SystemLibrary.execute_console_command(None, 'sg.${base}Quality', None)
142
+ except:
143
+ pass
144
+
145
+ # Get the output
146
+ console_output = sys.stdout.getvalue()
147
+ sys.stdout = old_stdout
148
+
149
+ # Parse the output to get the actual value
150
+ if 'sg.${base}Quality' in console_output:
151
+ # Extract the value from output like 'sg.ShadowQuality = "3"'
152
+ import re
153
+ match = re.search(r'sg\.${base}Quality\\s*=\\s*"(\\d+)"', console_output)
154
+ if match:
155
+ result['actual'] = int(match.group(1))
156
+ result['verified'] = True
157
+
158
+ result['method'] = 'ConsoleOnly'
159
+ except Exception as e:
160
+ # Even on error, the console command was applied
161
+ result['method'] = 'ConsoleOnly'
162
+ result['note'] = str(e)
163
+
164
+ print('RESULT:' + json.dumps(result))
165
+ `.trim();
166
+ /* eslint-enable no-useless-escape */
167
+ // Always try to apply through Python for consistency
168
+ try {
169
+ const pyResp = await this.bridge.executePython(py);
170
+ let out = '';
171
+ if (pyResp?.LogOutput && Array.isArray(pyResp.LogOutput)) {
172
+ out = pyResp.LogOutput.map((l) => l.Output || '').join('');
173
+ }
174
+ else if (typeof pyResp === 'string') {
175
+ out = pyResp;
176
+ }
177
+ else {
178
+ out = JSON.stringify(pyResp);
179
+ }
180
+ const m = out.match(/RESULT:({.*})/);
181
+ if (m) {
182
+ try {
183
+ const parsed = JSON.parse(m[1]);
184
+ const verified = parsed.success && (parsed.actual === params.level);
185
+ return {
186
+ success: true,
187
+ message: `${params.category} quality set to level ${params.level}`,
188
+ verified,
189
+ readback: parsed.actual,
190
+ method: parsed.method || 'Unknown'
191
+ };
192
+ }
193
+ catch {
194
+ // Fall through to simple success
195
+ }
196
+ }
197
+ }
198
+ catch {
199
+ // Ignore Python errors and fall through
200
+ }
201
+ // If Python fails, the console command was still applied
202
+ return {
203
+ success: true,
204
+ message: `${params.category} quality set to level ${params.level}`,
205
+ method: 'CVarOnly'
206
+ };
207
+ }
208
+ // Set resolution scale
209
+ async setResolutionScale(params) {
210
+ // Validate input
211
+ if (params.scale === undefined || params.scale === null || isNaN(params.scale)) {
212
+ return { success: false, error: 'Invalid scale parameter' };
213
+ }
214
+ // Clamp scale between 10% (0.1) and 200% (2.0) - Unreal Engine limits
215
+ // Note: r.ScreenPercentage takes values from 10 to 200, not 0.5 to 2.0
216
+ const clampedScale = Math.max(0.1, Math.min(2.0, params.scale));
217
+ const percentage = Math.round(clampedScale * 100);
218
+ // Ensure percentage is within Unreal's valid range
219
+ const finalPercentage = Math.max(10, Math.min(200, percentage));
220
+ const command = `r.ScreenPercentage ${finalPercentage}`;
221
+ try {
222
+ await this.bridge.executeConsoleCommand(command);
223
+ return {
224
+ success: true,
225
+ message: `Resolution scale set to ${finalPercentage}%`,
226
+ actualScale: finalPercentage / 100
227
+ };
228
+ }
229
+ catch (e) {
230
+ return { success: false, error: `Failed to set resolution scale: ${e}` };
231
+ }
232
+ }
233
+ // Enable/disable vsync
234
+ async setVSync(params) {
235
+ const command = `r.VSync ${params.enabled ? 1 : 0}`;
236
+ return this.bridge.executeConsoleCommand(command);
237
+ }
238
+ // Set frame rate limit
239
+ async setFrameRateLimit(params) {
240
+ const command = `t.MaxFPS ${params.maxFPS}`;
241
+ return this.bridge.executeConsoleCommand(command);
242
+ }
243
+ // Enable GPU timing
244
+ async enableGPUTiming(params) {
245
+ const command = `r.GPUStatsEnabled ${params.enabled ? 1 : 0}`;
246
+ return this.bridge.executeConsoleCommand(command);
247
+ }
248
+ // Memory report
249
+ async generateMemoryReport(params) {
250
+ const commands = [];
251
+ if (params.detailed) {
252
+ commands.push('memreport -full');
253
+ }
254
+ else {
255
+ commands.push('memreport');
256
+ }
257
+ if (params.outputPath) {
258
+ commands.push(`obj savepackage ${params.outputPath}`);
259
+ }
260
+ for (const cmd of commands) {
261
+ await this.bridge.executeConsoleCommand(cmd);
262
+ }
263
+ return { success: true, message: 'Memory report generated' };
264
+ }
265
+ // Texture streaming
266
+ async configureTextureStreaming(params) {
267
+ const commands = [];
268
+ commands.push(`r.TextureStreaming ${params.enabled ? 1 : 0}`);
269
+ if (params.poolSize !== undefined) {
270
+ commands.push(`r.Streaming.PoolSize ${params.poolSize}`);
271
+ }
272
+ if (params.boostPlayerLocation !== undefined) {
273
+ commands.push(`r.Streaming.UseFixedPoolSize ${params.boostPlayerLocation ? 1 : 0}`);
274
+ }
275
+ for (const cmd of commands) {
276
+ await this.bridge.executeConsoleCommand(cmd);
277
+ }
278
+ return { success: true, message: 'Texture streaming configured' };
279
+ }
280
+ // LOD settings
281
+ async configureLOD(params) {
282
+ const commands = [];
283
+ if (params.forceLOD !== undefined) {
284
+ commands.push(`r.ForceLOD ${params.forceLOD}`);
285
+ }
286
+ if (params.lodBias !== undefined) {
287
+ // Skeletal mesh LOD bias is an integer bias value
288
+ commands.push(`r.SkeletalMeshLODBias ${params.lodBias}`);
289
+ }
290
+ if (params.distanceScale !== undefined) {
291
+ // Apply distance scale to both static and skeletal meshes
292
+ commands.push(`r.StaticMeshLODDistanceScale ${params.distanceScale}`);
293
+ commands.push(`r.SkeletalMeshLODDistanceScale ${params.distanceScale}`);
294
+ }
295
+ for (const cmd of commands) {
296
+ await this.bridge.executeConsoleCommand(cmd);
297
+ }
298
+ return { success: true, message: 'LOD settings configured' };
299
+ }
300
+ // Apply a baseline performance profile (explicit CVar enforcement)
301
+ async applyBaselinePerformanceSettings(params) {
302
+ const p = {
303
+ distanceScale: params?.distanceScale ?? 1.0,
304
+ skeletalBias: params?.skeletalBias ?? 0,
305
+ vsync: params?.vsync ?? false,
306
+ maxFPS: params?.maxFPS ?? 60,
307
+ hzb: params?.hzb ?? true,
308
+ };
309
+ const commands = [
310
+ `r.StaticMeshLODDistanceScale ${p.distanceScale}`,
311
+ `r.SkeletalMeshLODDistanceScale ${p.distanceScale}`,
312
+ `r.SkeletalMeshLODBias ${p.skeletalBias}`,
313
+ `r.HZBOcclusion ${p.hzb ? 1 : 0}`,
314
+ `r.VSync ${p.vsync ? 1 : 0}`,
315
+ `t.MaxFPS ${p.maxFPS}`,
316
+ ];
317
+ for (const cmd of commands) {
318
+ await this.bridge.executeConsoleCommand(cmd);
319
+ }
320
+ return { success: true, message: 'Baseline performance settings applied', params: p };
321
+ }
322
+ // Draw call optimization
323
+ async optimizeDrawCalls(params) {
324
+ const commands = [];
325
+ if (params.enableInstancing !== undefined) {
326
+ commands.push(`r.MeshDrawCommands.DynamicInstancing ${params.enableInstancing ? 1 : 0}`);
327
+ }
328
+ // Avoid using r.RHICmdBypass; it's a low-level debug toggle and not suitable for general batching control
329
+ if (params.mergeActors) {
330
+ commands.push('MergeActors');
331
+ }
332
+ for (const cmd of commands) {
333
+ await this.bridge.executeConsoleCommand(cmd);
334
+ }
335
+ return { success: true, message: 'Draw call optimization configured' };
336
+ }
337
+ // Occlusion culling
338
+ async configureOcclusionCulling(params) {
339
+ const commands = [];
340
+ // Enable/disable HZB occlusion (boolean)
341
+ commands.push(`r.HZBOcclusion ${params.enabled ? 1 : 0}`);
342
+ // Optional freeze rendering toggle
343
+ if (params.freezeRendering !== undefined) {
344
+ commands.push(`FreezeRendering ${params.freezeRendering ? 1 : 0}`);
345
+ }
346
+ for (const cmd of commands) {
347
+ await this.bridge.executeConsoleCommand(cmd);
348
+ }
349
+ return { success: true, message: 'Occlusion culling configured' };
350
+ }
351
+ // Shader compilation
352
+ async optimizeShaders(params) {
353
+ const commands = [];
354
+ if (params.compileOnDemand !== undefined) {
355
+ commands.push(`r.ShaderDevelopmentMode ${params.compileOnDemand ? 1 : 0}`);
356
+ }
357
+ if (params.cacheShaders !== undefined) {
358
+ commands.push(`r.ShaderPipelineCache.Enabled ${params.cacheShaders ? 1 : 0}`);
359
+ }
360
+ if (params.reducePermutations) {
361
+ commands.push('RecompileShaders changed');
362
+ }
363
+ for (const cmd of commands) {
364
+ await this.bridge.executeConsoleCommand(cmd);
365
+ }
366
+ return { success: true, message: 'Shader optimization configured' };
367
+ }
368
+ // Nanite settings
369
+ async configureNanite(params) {
370
+ const commands = [];
371
+ commands.push(`r.Nanite ${params.enabled ? 1 : 0}`);
372
+ if (params.maxPixelsPerEdge !== undefined) {
373
+ commands.push(`r.Nanite.MaxPixelsPerEdge ${params.maxPixelsPerEdge}`);
374
+ }
375
+ if (params.streamingPoolSize !== undefined) {
376
+ commands.push(`r.Nanite.StreamingPoolSize ${params.streamingPoolSize}`);
377
+ }
378
+ for (const cmd of commands) {
379
+ await this.bridge.executeConsoleCommand(cmd);
380
+ }
381
+ return { success: true, message: 'Nanite configured' };
382
+ }
383
+ // World Partition streaming
384
+ async configureWorldPartition(params) {
385
+ const commands = [];
386
+ commands.push(`wp.Runtime.EnableStreaming ${params.enabled ? 1 : 0}`);
387
+ if (params.streamingDistance !== undefined) {
388
+ commands.push(`wp.Runtime.StreamingDistance ${params.streamingDistance}`);
389
+ }
390
+ if (params.cellSize !== undefined) {
391
+ commands.push(`wp.Runtime.CellSize ${params.cellSize}`);
392
+ }
393
+ for (const cmd of commands) {
394
+ await this.bridge.executeConsoleCommand(cmd);
395
+ }
396
+ return { success: true, message: 'World Partition configured' };
397
+ }
398
+ // Benchmark
399
+ async runBenchmark(params) {
400
+ const duration = params.duration || 60;
401
+ // Start recording and GPU profiling
402
+ await this.bridge.executeConsoleCommand('stat startfile');
403
+ await this.bridge.executeConsoleCommand('profilegpu');
404
+ // Wait for the requested duration
405
+ await new Promise(resolve => setTimeout(resolve, duration * 1000));
406
+ // Stop recording and clear stats
407
+ await this.bridge.executeConsoleCommand('stat stopfile');
408
+ await this.bridge.executeConsoleCommand('stat none');
409
+ return { success: true, message: `Benchmark completed for ${duration} seconds` };
410
+ }
411
+ }
412
+ //# sourceMappingURL=performance.js.map