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,416 @@
1
+ export class AudioTools {
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
+ // Create sound cue
20
+ async createSoundCue(params) {
21
+ const path = params.savePath || '/Game/Audio/Cues';
22
+ const py = `
23
+ import unreal
24
+ import json
25
+ name = r"${params.name}"
26
+ path = r"${path}"
27
+ try:
28
+ asset_tools = unreal.AssetToolsHelpers.get_asset_tools()
29
+ try:
30
+ factory = unreal.SoundCueFactoryNew()
31
+ except Exception:
32
+ factory = None
33
+ if not factory:
34
+ print('RESULT:' + json.dumps({'success': False, 'error': 'SoundCueFactoryNew unavailable'}))
35
+ else:
36
+ asset = asset_tools.create_asset(asset_name=name, package_path=path, asset_class=unreal.SoundCue, factory=factory)
37
+ if asset:
38
+ if ${params.wavePath !== undefined ? 'True' : 'False'}:
39
+ try:
40
+ wave_path = r"${params.wavePath || ''}"
41
+ if wave_path and unreal.EditorAssetLibrary.does_asset_exist(wave_path):
42
+ snd = unreal.EditorAssetLibrary.load_asset(wave_path)
43
+ # Simple node hookup via SoundCueGraph is non-trivial via Python; leave as empty cue
44
+ except Exception:
45
+ pass
46
+ unreal.EditorAssetLibrary.save_asset(f"{path}/{name}")
47
+ print('RESULT:' + json.dumps({'success': True}))
48
+ else:
49
+ print('RESULT:' + json.dumps({'success': False, 'error': 'Failed to create SoundCue'}))
50
+ except Exception as e:
51
+ print('RESULT:' + json.dumps({'success': False, 'error': str(e)}))
52
+ `.trim();
53
+ try {
54
+ const resp = await this.bridge.executePython(py);
55
+ const out = typeof resp === 'string' ? resp : JSON.stringify(resp);
56
+ const m = out.match(/RESULT:({.*})/);
57
+ if (m) {
58
+ try {
59
+ const parsed = JSON.parse(m[1]);
60
+ return parsed.success ? { success: true, message: 'Sound cue created' } : { success: false, error: parsed.error };
61
+ }
62
+ catch { }
63
+ }
64
+ return { success: true, message: 'Sound cue creation attempted' };
65
+ }
66
+ catch (e) {
67
+ return { success: false, error: `Failed to create sound cue: ${e}` };
68
+ }
69
+ }
70
+ // Play sound at location
71
+ async playSoundAtLocation(params) {
72
+ const volume = params.volume ?? 1.0;
73
+ const pitch = params.pitch ?? 1.0;
74
+ const startTime = params.startTime ?? 0.0;
75
+ const py = `
76
+ import unreal
77
+ import json
78
+ loc = unreal.Vector(${params.location[0]}, ${params.location[1]}, ${params.location[2]})
79
+ path = r"${params.soundPath}"
80
+ try:
81
+ if not unreal.EditorAssetLibrary.does_asset_exist(path):
82
+ print('RESULT:' + json.dumps({'success': False, 'error': 'Sound asset not found'}))
83
+ else:
84
+ snd = unreal.EditorAssetLibrary.load_asset(path)
85
+ # Get editor world via EditorSubsystem first to avoid deprecation
86
+ try:
87
+ world = unreal.EditorSubsystemLibrary.get_editor_world()
88
+ except Exception:
89
+ try:
90
+ world = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem).get_editor_world()
91
+ except Exception:
92
+ world = unreal.EditorLevelLibrary.get_editor_world()
93
+ rot = unreal.Rotator(0.0, 0.0, 0.0)
94
+ # Use spawn_* variant with explicit rotation before optional floats
95
+ unreal.GameplayStatics.spawn_sound_at_location(world, snd, loc, rot, ${volume}, ${pitch}, ${startTime})
96
+ print('RESULT:' + json.dumps({'success': True}))
97
+ except Exception as e:
98
+ print('RESULT:' + json.dumps({'success': False, 'error': str(e)}))
99
+ `.trim();
100
+ try {
101
+ const resp = await this.bridge.executePython(py);
102
+ const out = typeof resp === 'string' ? resp : JSON.stringify(resp);
103
+ const m = out.match(/RESULT:({.*})/);
104
+ if (m) {
105
+ try {
106
+ const parsed = JSON.parse(m[1]);
107
+ return parsed.success ? { success: true, message: 'Sound played' } : { success: false, error: parsed.error };
108
+ }
109
+ catch { }
110
+ }
111
+ return { success: true, message: 'Sound play attempted' };
112
+ }
113
+ catch (e) {
114
+ return { success: false, error: `Failed to play sound: ${e}` };
115
+ }
116
+ }
117
+ // Play sound 2D
118
+ async playSound2D(params) {
119
+ const volume = params.volume ?? 1.0;
120
+ const pitch = params.pitch ?? 1.0;
121
+ const startTime = params.startTime ?? 0.0;
122
+ const py = `
123
+ import unreal
124
+ import json
125
+ path = r"${params.soundPath}"
126
+ try:
127
+ if not unreal.EditorAssetLibrary.does_asset_exist(path):
128
+ print('RESULT:' + json.dumps({'success': False, 'error': 'Sound asset not found'}))
129
+ else:
130
+ snd = unreal.EditorAssetLibrary.load_asset(path)
131
+ # Get editor world via EditorSubsystem first to avoid deprecation
132
+ try:
133
+ world = unreal.EditorSubsystemLibrary.get_editor_world()
134
+ except Exception:
135
+ try:
136
+ world = unreal.get_editor_subsystem(unreal.UnrealEditorSubsystem).get_editor_world()
137
+ except Exception:
138
+ world = unreal.EditorLevelLibrary.get_editor_world()
139
+ ok = False
140
+ try:
141
+ unreal.GameplayStatics.spawn_sound_2d(world, snd, ${volume}, ${pitch}, ${startTime})
142
+ ok = True
143
+ except AttributeError:
144
+ try:
145
+ unreal.GameplayStatics.play_sound_2d(world, snd, ${volume}, ${pitch}, ${startTime})
146
+ ok = True
147
+ except AttributeError:
148
+ # Fallback: play at camera location as 2D substitute
149
+ try:
150
+ info = unreal.EditorLevelLibrary.get_level_viewport_camera_info()
151
+ cam_loc = info[0] if isinstance(info, (list, tuple)) and len(info) > 0 else unreal.Vector(0.0, 0.0, 0.0)
152
+ except Exception:
153
+ cam_loc = unreal.Vector(0.0, 0.0, 0.0)
154
+ rot = unreal.Rotator(0.0, 0.0, 0.0)
155
+ unreal.GameplayStatics.spawn_sound_at_location(world, snd, cam_loc, rot, ${volume}, ${pitch}, ${startTime})
156
+ ok = True
157
+ print('RESULT:' + json.dumps({'success': True} if ok else {'success': False, 'error': 'No suitable 2D playback method found'}))
158
+ except Exception as e:
159
+ print('RESULT:' + json.dumps({'success': False, 'error': str(e)}))
160
+ `.trim();
161
+ try {
162
+ const resp = await this.bridge.executePython(py);
163
+ const out = typeof resp === 'string' ? resp : JSON.stringify(resp);
164
+ const m = out.match(/RESULT:({.*})/);
165
+ if (m) {
166
+ try {
167
+ const parsed = JSON.parse(m[1]);
168
+ return parsed.success ? { success: true, message: 'Sound2D played' } : { success: false, error: parsed.error };
169
+ }
170
+ catch { }
171
+ }
172
+ return { success: true, message: 'Sound2D play attempted' };
173
+ }
174
+ catch (e) {
175
+ return { success: false, error: `Failed to play sound2D: ${e}` };
176
+ }
177
+ }
178
+ // Create audio component
179
+ async createAudioComponent(params) {
180
+ const commands = [];
181
+ commands.push(`AddAudioComponent ${params.actorName} ${params.componentName} ${params.soundPath}`);
182
+ if (params.autoPlay !== undefined) {
183
+ commands.push(`SetAudioComponentAutoPlay ${params.actorName}.${params.componentName} ${params.autoPlay}`);
184
+ }
185
+ if (params.is3D !== undefined) {
186
+ commands.push(`SetAudioComponent3D ${params.actorName}.${params.componentName} ${params.is3D}`);
187
+ }
188
+ for (const cmd of commands) {
189
+ await this.bridge.executeConsoleCommand(cmd);
190
+ }
191
+ return { success: true, message: `Audio component ${params.componentName} added to ${params.actorName}` };
192
+ }
193
+ // Set sound attenuation
194
+ async setSoundAttenuation(params) {
195
+ const commands = [];
196
+ commands.push(`CreateAttenuationSettings ${params.name}`);
197
+ if (params.innerRadius !== undefined) {
198
+ commands.push(`SetAttenuationInnerRadius ${params.name} ${params.innerRadius}`);
199
+ }
200
+ if (params.falloffDistance !== undefined) {
201
+ commands.push(`SetAttenuationFalloffDistance ${params.name} ${params.falloffDistance}`);
202
+ }
203
+ if (params.attenuationShape) {
204
+ commands.push(`SetAttenuationShape ${params.name} ${params.attenuationShape}`);
205
+ }
206
+ if (params.falloffMode) {
207
+ commands.push(`SetAttenuationFalloffMode ${params.name} ${params.falloffMode}`);
208
+ }
209
+ for (const cmd of commands) {
210
+ await this.bridge.executeConsoleCommand(cmd);
211
+ }
212
+ return { success: true, message: `Attenuation settings ${params.name} configured` };
213
+ }
214
+ // Create sound class
215
+ async createSoundClass(params) {
216
+ const commands = [];
217
+ const parent = params.parentClass || 'Master';
218
+ commands.push(`CreateSoundClass ${params.name} ${parent}`);
219
+ if (params.properties) {
220
+ if (params.properties.volume !== undefined) {
221
+ commands.push(`SetSoundClassVolume ${params.name} ${params.properties.volume}`);
222
+ }
223
+ if (params.properties.pitch !== undefined) {
224
+ commands.push(`SetSoundClassPitch ${params.name} ${params.properties.pitch}`);
225
+ }
226
+ if (params.properties.lowPassFilterFrequency !== undefined) {
227
+ commands.push(`SetSoundClassLowPassFilter ${params.name} ${params.properties.lowPassFilterFrequency}`);
228
+ }
229
+ if (params.properties.attenuationDistanceScale !== undefined) {
230
+ commands.push(`SetSoundClassAttenuationScale ${params.name} ${params.properties.attenuationDistanceScale}`);
231
+ }
232
+ }
233
+ for (const cmd of commands) {
234
+ await this.bridge.executeConsoleCommand(cmd);
235
+ }
236
+ return { success: true, message: `Sound class ${params.name} created` };
237
+ }
238
+ // Create sound mix
239
+ async createSoundMix(params) {
240
+ const commands = [];
241
+ commands.push(`CreateSoundMix ${params.name}`);
242
+ if (params.classAdjusters) {
243
+ for (const adjuster of params.classAdjusters) {
244
+ commands.push(`AddSoundMixClassAdjuster ${params.name} ${adjuster.soundClass}`);
245
+ if (adjuster.volumeAdjuster !== undefined) {
246
+ commands.push(`SetSoundMixVolume ${params.name} ${adjuster.soundClass} ${adjuster.volumeAdjuster}`);
247
+ }
248
+ if (adjuster.pitchAdjuster !== undefined) {
249
+ commands.push(`SetSoundMixPitch ${params.name} ${adjuster.soundClass} ${adjuster.pitchAdjuster}`);
250
+ }
251
+ if (adjuster.fadeInTime !== undefined) {
252
+ commands.push(`SetSoundMixFadeIn ${params.name} ${adjuster.soundClass} ${adjuster.fadeInTime}`);
253
+ }
254
+ if (adjuster.fadeOutTime !== undefined) {
255
+ commands.push(`SetSoundMixFadeOut ${params.name} ${adjuster.soundClass} ${adjuster.fadeOutTime}`);
256
+ }
257
+ }
258
+ }
259
+ for (const cmd of commands) {
260
+ await this.bridge.executeConsoleCommand(cmd);
261
+ }
262
+ return { success: true, message: `Sound mix ${params.name} created` };
263
+ }
264
+ // Push/Pop sound mix
265
+ async pushSoundMix(params) {
266
+ const command = `PushSoundMix ${params.mixName}`;
267
+ return this.bridge.executeConsoleCommand(command);
268
+ }
269
+ async popSoundMix(params) {
270
+ const command = `PopSoundMix ${params.mixName}`;
271
+ return this.bridge.executeConsoleCommand(command);
272
+ }
273
+ // Set master volume
274
+ async setMasterVolume(params) {
275
+ // Clamp volume between 0 and 1
276
+ const vol = Math.max(0.0, Math.min(1.0, params.volume));
277
+ // Use the proper Unreal Engine audio command
278
+ // Note: au.Master.Volume is the correct console variable for master volume
279
+ const command = `au.Master.Volume ${vol}`;
280
+ try {
281
+ await this.bridge.executeConsoleCommand(command);
282
+ return { success: true, message: `Master volume set to ${vol}` };
283
+ }
284
+ catch (e) {
285
+ // Fallback to Python method if console command fails
286
+ const py = `
287
+ import unreal
288
+ import json
289
+ try:
290
+ # Try using AudioMixerBlueprintLibrary if available
291
+ try:
292
+ unreal.AudioMixerBlueprintLibrary.set_overall_volume_multiplier(${vol})
293
+ print('RESULT:' + json.dumps({'success': True}))
294
+ except AttributeError:
295
+ # Fallback to GameplayStatics method
296
+ try:
297
+ world = unreal.EditorLevelLibrary.get_editor_world()
298
+ unreal.GameplayStatics.set_global_pitch_modulation(world, 1.0, 0.0) # Reset pitch
299
+ unreal.GameplayStatics.set_global_time_dilation(world, 1.0) # Reset time
300
+ # Note: There's no direct master volume in GameplayStatics, use sound class
301
+ print('RESULT:' + json.dumps({'success': False, 'error': 'Master volume control not available, use sound classes instead'}))
302
+ except Exception as e2:
303
+ print('RESULT:' + json.dumps({'success': False, 'error': str(e2)}))
304
+ except Exception as e:
305
+ print('RESULT:' + json.dumps({'success': False, 'error': str(e)}))
306
+ `.trim();
307
+ try {
308
+ const resp = await this.bridge.executePython(py);
309
+ const out = typeof resp === 'string' ? resp : JSON.stringify(resp);
310
+ const m = out.match(/RESULT:({.*})/);
311
+ if (m) {
312
+ try {
313
+ const parsed = JSON.parse(m[1]);
314
+ return parsed.success
315
+ ? { success: true, message: `Master volume set to ${vol}` }
316
+ : { success: false, error: parsed.error };
317
+ }
318
+ catch { }
319
+ }
320
+ return { success: true, message: 'Master volume set command executed' };
321
+ }
322
+ catch {
323
+ return { success: false, error: `Failed to set master volume: ${e}` };
324
+ }
325
+ }
326
+ }
327
+ // Create ambient sound
328
+ async createAmbientSound(params) {
329
+ const commands = [];
330
+ commands.push(`SpawnAmbientSound ${params.name} ${params.location.join(' ')} ${params.soundPath}`);
331
+ if (params.volume !== undefined) {
332
+ commands.push(`SetAmbientVolume ${params.name} ${params.volume}`);
333
+ }
334
+ if (params.radius !== undefined) {
335
+ commands.push(`SetAmbientRadius ${params.name} ${params.radius}`);
336
+ }
337
+ if (params.autoPlay !== undefined) {
338
+ commands.push(`SetAmbientAutoPlay ${params.name} ${params.autoPlay}`);
339
+ }
340
+ for (const cmd of commands) {
341
+ await this.bridge.executeConsoleCommand(cmd);
342
+ }
343
+ return { success: true, message: `Ambient sound ${params.name} created` };
344
+ }
345
+ // Create reverb zone
346
+ async createReverbZone(params) {
347
+ const commands = [];
348
+ commands.push(`CreateReverbVolume ${params.name} ${params.location.join(' ')} ${params.size.join(' ')}`);
349
+ if (params.reverbEffect) {
350
+ commands.push(`SetReverbEffect ${params.name} ${params.reverbEffect}`);
351
+ }
352
+ if (params.volume !== undefined) {
353
+ commands.push(`SetReverbVolume ${params.name} ${params.volume}`);
354
+ }
355
+ if (params.fadeTime !== undefined) {
356
+ commands.push(`SetReverbFadeTime ${params.name} ${params.fadeTime}`);
357
+ }
358
+ for (const cmd of commands) {
359
+ await this.bridge.executeConsoleCommand(cmd);
360
+ }
361
+ return { success: true, message: `Reverb zone ${params.name} created` };
362
+ }
363
+ // Audio analysis
364
+ async enableAudioAnalysis(params) {
365
+ const commands = [];
366
+ commands.push(`EnableAudioAnalysis ${params.enabled}`);
367
+ if (params.enabled && params.fftSize) {
368
+ commands.push(`SetFFTSize ${params.fftSize}`);
369
+ }
370
+ if (params.enabled && params.outputType) {
371
+ commands.push(`SetAudioAnalysisOutput ${params.outputType}`);
372
+ }
373
+ for (const cmd of commands) {
374
+ await this.bridge.executeConsoleCommand(cmd);
375
+ }
376
+ return { success: true, message: `Audio analysis ${params.enabled ? 'enabled' : 'disabled'}` };
377
+ }
378
+ // Stop all sounds
379
+ async stopAllSounds() {
380
+ return this.bridge.executeConsoleCommand('StopAllSounds');
381
+ }
382
+ // Fade sound
383
+ async fadeSound(params) {
384
+ const type = params.fadeType || 'FadeTo';
385
+ const command = `${type}Sound ${params.soundName} ${params.targetVolume} ${params.fadeTime}`;
386
+ return this.bridge.executeConsoleCommand(command);
387
+ }
388
+ // Set doppler effect
389
+ async setDopplerEffect(params) {
390
+ const commands = [];
391
+ commands.push(`EnableDoppler ${params.enabled}`);
392
+ if (params.scale !== undefined) {
393
+ commands.push(`SetDopplerScale ${params.scale}`);
394
+ }
395
+ for (const cmd of commands) {
396
+ await this.bridge.executeConsoleCommand(cmd);
397
+ }
398
+ return { success: true, message: `Doppler effect ${params.enabled ? 'enabled' : 'disabled'}` };
399
+ }
400
+ // Audio occlusion
401
+ async setAudioOcclusion(params) {
402
+ const commands = [];
403
+ commands.push(`EnableAudioOcclusion ${params.enabled}`);
404
+ if (params.lowPassFilterFrequency !== undefined) {
405
+ commands.push(`SetOcclusionLowPassFilter ${params.lowPassFilterFrequency}`);
406
+ }
407
+ if (params.volumeAttenuation !== undefined) {
408
+ commands.push(`SetOcclusionVolumeAttenuation ${params.volumeAttenuation}`);
409
+ }
410
+ for (const cmd of commands) {
411
+ await this.bridge.executeConsoleCommand(cmd);
412
+ }
413
+ return { success: true, message: `Audio occlusion ${params.enabled ? 'enabled' : 'disabled'}` };
414
+ }
415
+ }
416
+ //# sourceMappingURL=audio.js.map
@@ -0,0 +1,144 @@
1
+ import { UnrealBridge } from '../unreal-bridge.js';
2
+ export declare class BlueprintTools {
3
+ private bridge;
4
+ constructor(bridge: UnrealBridge);
5
+ /**
6
+ * Create Blueprint
7
+ */
8
+ createBlueprint(params: {
9
+ name: string;
10
+ blueprintType: 'Actor' | 'Pawn' | 'Character' | 'GameMode' | 'PlayerController' | 'HUD' | 'ActorComponent';
11
+ savePath?: string;
12
+ parentClass?: string;
13
+ }): Promise<{
14
+ success: boolean;
15
+ message: string;
16
+ error: string | undefined;
17
+ path?: undefined;
18
+ } | {
19
+ success: boolean;
20
+ message: string;
21
+ path: string;
22
+ error?: undefined;
23
+ } | {
24
+ success: boolean;
25
+ error: string;
26
+ message?: undefined;
27
+ path?: undefined;
28
+ }>;
29
+ /**
30
+ * Add Component to Blueprint
31
+ */
32
+ addComponent(params: {
33
+ blueprintName: string;
34
+ componentType: string;
35
+ componentName: string;
36
+ attachTo?: string;
37
+ transform?: {
38
+ location?: [number, number, number];
39
+ rotation?: [number, number, number];
40
+ scale?: [number, number, number];
41
+ };
42
+ }): Promise<{
43
+ success: boolean;
44
+ message: string;
45
+ error?: undefined;
46
+ } | {
47
+ success: boolean;
48
+ message: string;
49
+ error: string;
50
+ } | {
51
+ success: boolean;
52
+ error: string;
53
+ message?: undefined;
54
+ }>;
55
+ /**
56
+ * Add Variable to Blueprint
57
+ */
58
+ addVariable(params: {
59
+ blueprintName: string;
60
+ variableName: string;
61
+ variableType: string;
62
+ defaultValue?: any;
63
+ category?: string;
64
+ isReplicated?: boolean;
65
+ isPublic?: boolean;
66
+ }): Promise<{
67
+ success: boolean;
68
+ message: string;
69
+ error?: undefined;
70
+ } | {
71
+ success: boolean;
72
+ error: string;
73
+ message?: undefined;
74
+ }>;
75
+ /**
76
+ * Add Function to Blueprint
77
+ */
78
+ addFunction(params: {
79
+ blueprintName: string;
80
+ functionName: string;
81
+ inputs?: Array<{
82
+ name: string;
83
+ type: string;
84
+ }>;
85
+ outputs?: Array<{
86
+ name: string;
87
+ type: string;
88
+ }>;
89
+ isPublic?: boolean;
90
+ category?: string;
91
+ }): Promise<{
92
+ success: boolean;
93
+ message: string;
94
+ error?: undefined;
95
+ } | {
96
+ success: boolean;
97
+ error: string;
98
+ message?: undefined;
99
+ }>;
100
+ /**
101
+ * Add Event to Blueprint
102
+ */
103
+ addEvent(params: {
104
+ blueprintName: string;
105
+ eventType: 'BeginPlay' | 'Tick' | 'EndPlay' | 'BeginOverlap' | 'EndOverlap' | 'Hit' | 'Custom';
106
+ customEventName?: string;
107
+ parameters?: Array<{
108
+ name: string;
109
+ type: string;
110
+ }>;
111
+ }): Promise<{
112
+ success: boolean;
113
+ message: string;
114
+ error?: undefined;
115
+ } | {
116
+ success: boolean;
117
+ error: string;
118
+ message?: undefined;
119
+ }>;
120
+ /**
121
+ * Compile Blueprint
122
+ */
123
+ compileBlueprint(params: {
124
+ blueprintName: string;
125
+ saveAfterCompile?: boolean;
126
+ }): Promise<{
127
+ success: boolean;
128
+ message: string;
129
+ error?: undefined;
130
+ } | {
131
+ success: boolean;
132
+ error: string;
133
+ message?: undefined;
134
+ }>;
135
+ /**
136
+ * Get default parent class for blueprint type
137
+ */
138
+ private _getDefaultParentClass;
139
+ /**
140
+ * Helper function to execute console commands
141
+ */
142
+ private _executeCommand;
143
+ }
144
+ //# sourceMappingURL=blueprint.d.ts.map