ue-mcp 1.2.1 → 1.2.2

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 (54) hide show
  1. package/dist/context-cli.js +16 -16
  2. package/dist/engine-observer.js +68 -68
  3. package/dist/flow/guard.d.ts +26 -37
  4. package/dist/flow/guard.js +40 -25
  5. package/dist/flow/guard.js.map +1 -1
  6. package/dist/flow/guarded-bridge.d.ts +0 -10
  7. package/dist/flow/guarded-bridge.js +18 -23
  8. package/dist/flow/guarded-bridge.js.map +1 -1
  9. package/dist/flow/schema.d.ts +276 -16
  10. package/dist/flow/task-guards.d.ts +1 -1
  11. package/dist/flow/task-guards.js +44 -68
  12. package/dist/flow/task-guards.js.map +1 -1
  13. package/dist/instructions.js +130 -130
  14. package/dist/plugin-cli.js +299 -299
  15. package/dist/tool-counts.json +2 -2
  16. package/package.json +2 -2
  17. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.cpp +76 -76
  18. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/EngineStatusHooks.h +27 -27
  19. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.cpp +128 -128
  20. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.h +63 -63
  21. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers_ControlRig.cpp +230 -230
  22. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers_Struct.cpp +323 -323
  23. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers_Internal.h +20 -20
  24. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ChooserHandlers_Nested.cpp +537 -537
  25. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.h +77 -77
  26. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers_Build.cpp +353 -353
  27. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +18 -18
  28. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers_InputRuntime.cpp +246 -246
  29. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +597 -597
  30. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +51 -51
  31. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +878 -878
  32. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers_Sculpt.cpp +449 -449
  33. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Function.cpp +275 -275
  34. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers_Graph.cpp +551 -551
  35. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.cpp +531 -531
  36. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.h +28 -28
  37. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +677 -677
  38. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +822 -822
  39. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +22 -22
  40. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +218 -218
  41. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.h +17 -17
  42. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.cpp +46 -46
  43. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/VolumeHelpers_Internal.h +23 -23
  44. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/MCPExternalRegistry.cpp +83 -83
  45. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/UE_MCP_BridgeModule.h +14 -14
  46. package/plugin/ue_mcp_bridge/Source/UE_MCP_BridgeStatus/Private/UE_MCP_BridgeStatusModule.cpp +37 -37
  47. package/dist/manifest-signature.d.ts +0 -1
  48. package/dist/manifest-signature.js +0 -53
  49. package/dist/manifest-signature.js.map +0 -1
  50. package/dist/pie/schema.d.ts +0 -791
  51. package/dist/pie/schema.js +0 -151
  52. package/dist/pie/schema.js.map +0 -1
  53. package/dist/watch-cli.js.map +0 -1
  54. /package/plugin/ue_mcp_bridge/{ue_mcp_bridge.uplugin → UE_MCP_Bridge.uplugin} +0 -0
@@ -1,353 +1,353 @@
1
- // Split from EditorHandlers.cpp to keep that file under 3k lines.
2
- // All functions below are still members of FEditorHandlers - this file is a
3
- // translation-unit partition, not a new class. Handler registration
4
- // stays in EditorHandlers.cpp::RegisterHandlers.
5
-
6
- #include "EditorHandlers.h"
7
- #include "HandlerRegistry.h"
8
- #include "HandlerUtils.h"
9
- #include "Editor.h"
10
- #include "Editor/EditorEngine.h"
11
- #include "FileHelpers.h"
12
- #include "Engine/World.h"
13
- #include "Engine/Engine.h"
14
- #include "GameFramework/Actor.h"
15
- #include "Misc/Paths.h"
16
- #include "Misc/FileHelper.h"
17
- #include "Misc/CommandLine.h"
18
- #include "HAL/PlatformProcess.h"
19
- #include "HAL/PlatformFileManager.h"
20
- #include "HAL/PlatformFile.h"
21
- #include "Modules/ModuleManager.h"
22
- #if PLATFORM_WINDOWS
23
- #include "ILiveCodingModule.h"
24
- #endif
25
- #include "Kismet/KismetSystemLibrary.h"
26
- #include "EditorValidatorSubsystem.h"
27
- #include "Dom/JsonObject.h"
28
- #include "Dom/JsonValue.h"
29
-
30
- TSharedPtr<FJsonValue> FEditorHandlers::BuildLighting(const TSharedPtr<FJsonObject>& Params)
31
- {
32
- REQUIRE_EDITOR_WORLD(World);
33
-
34
- FString Quality = OptionalString(Params, TEXT("quality"), TEXT("Preview"));
35
-
36
- // Map quality string to console command
37
- FString Command;
38
- if (Quality == TEXT("Preview"))
39
- {
40
- Command = TEXT("BUILD LIGHTING QUALITY=Preview");
41
- }
42
- else if (Quality == TEXT("Medium"))
43
- {
44
- Command = TEXT("BUILD LIGHTING QUALITY=Medium");
45
- }
46
- else if (Quality == TEXT("High"))
47
- {
48
- Command = TEXT("BUILD LIGHTING QUALITY=High");
49
- }
50
- else if (Quality == TEXT("Production"))
51
- {
52
- Command = TEXT("BUILD LIGHTING QUALITY=Production");
53
- }
54
- else
55
- {
56
- Command = TEXT("BUILD LIGHTING QUALITY=Preview");
57
- }
58
-
59
- UKismetSystemLibrary::ExecuteConsoleCommand(World, Command, nullptr);
60
-
61
- auto Result = MCPSuccess();
62
- Result->SetStringField(TEXT("quality"), Quality);
63
- Result->SetStringField(TEXT("command"), Command);
64
- Result->SetStringField(TEXT("message"), FString::Printf(TEXT("Lighting build triggered (%s)"), *Quality));
65
- return MCPResult(Result);
66
- }
67
-
68
-
69
- TSharedPtr<FJsonValue> FEditorHandlers::BuildAll(const TSharedPtr<FJsonObject>& Params)
70
- {
71
- REQUIRE_EDITOR_WORLD(World);
72
-
73
- // Execute full build: geometry, lighting, and paths
74
- UKismetSystemLibrary::ExecuteConsoleCommand(World, TEXT("MAP REBUILD"), nullptr);
75
- UKismetSystemLibrary::ExecuteConsoleCommand(World, TEXT("BUILD LIGHTING"), nullptr);
76
- UKismetSystemLibrary::ExecuteConsoleCommand(World, TEXT("RebuildNavigation"), nullptr);
77
-
78
- auto Result = MCPSuccess();
79
- Result->SetStringField(TEXT("message"), TEXT("Build All triggered (geometry + lighting + navigation)"));
80
- return MCPResult(Result);
81
- }
82
-
83
-
84
- TSharedPtr<FJsonValue> FEditorHandlers::ValidateAssets(const TSharedPtr<FJsonObject>& Params)
85
- {
86
- FString Directory = OptionalString(Params, TEXT("directory"), TEXT("/Game/"));
87
-
88
- // Try to use the EditorValidatorSubsystem if available
89
- UEditorValidatorSubsystem* ValidatorSubsystem = GEditor ? GEditor->GetEditorSubsystem<UEditorValidatorSubsystem>() : nullptr;
90
-
91
- if (ValidatorSubsystem)
92
- {
93
- // Use the DataValidation console command for broad validation
94
- if (GEditor && GEditor->GetEditorWorldContext().World())
95
- {
96
- FString Command = FString::Printf(TEXT("DataValidation.ValidateAssets %s"), *Directory);
97
- UKismetSystemLibrary::ExecuteConsoleCommand(
98
- GEditor->GetEditorWorldContext().World(),
99
- Command,
100
- nullptr
101
- );
102
- }
103
-
104
- auto Result = MCPSuccess();
105
- Result->SetStringField(TEXT("directory"), Directory);
106
- Result->SetStringField(TEXT("message"), TEXT("Asset validation triggered via EditorValidatorSubsystem"));
107
- return MCPResult(Result);
108
- }
109
- else
110
- {
111
- // Fallback: trigger via console command
112
- if (GEditor && GEditor->GetEditorWorldContext().World())
113
- {
114
- UKismetSystemLibrary::ExecuteConsoleCommand(
115
- GEditor->GetEditorWorldContext().World(),
116
- TEXT("DataValidation.ValidateAssets"),
117
- nullptr
118
- );
119
- }
120
-
121
- auto Result = MCPSuccess();
122
- Result->SetStringField(TEXT("directory"), Directory);
123
- Result->SetStringField(TEXT("message"), TEXT("Asset validation triggered via console command"));
124
- return MCPResult(Result);
125
- }
126
- }
127
-
128
-
129
- TSharedPtr<FJsonValue> FEditorHandlers::CookContent(const TSharedPtr<FJsonObject>& Params)
130
- {
131
- REQUIRE_EDITOR_WORLD(World);
132
-
133
- FString Platform = OptionalString(Params, TEXT("platform"), TEXT("Windows"));
134
-
135
- FString Command = FString::Printf(TEXT("CookOnTheFly -TargetPlatform=%s"), *Platform);
136
- UKismetSystemLibrary::ExecuteConsoleCommand(World, Command, nullptr);
137
-
138
- auto Result = MCPSuccess();
139
- Result->SetStringField(TEXT("platform"), Platform);
140
- Result->SetStringField(TEXT("command"), Command);
141
- Result->SetStringField(TEXT("message"), FString::Printf(TEXT("Cook triggered for %s"), *Platform));
142
- return MCPResult(Result);
143
- }
144
-
145
-
146
- TSharedPtr<FJsonValue> FEditorHandlers::HotReload(const TSharedPtr<FJsonObject>& Params)
147
- {
148
- #if PLATFORM_WINDOWS
149
- ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
150
- if (LiveCoding && LiveCoding->IsEnabledForSession())
151
- {
152
- if (LiveCoding->IsCompiling())
153
- {
154
- auto Result = MCPSuccess();
155
- Result->SetStringField(TEXT("message"), TEXT("Live Coding compile already in progress"));
156
- return MCPResult(Result);
157
- }
158
-
159
- LiveCoding->EnableByDefault(true);
160
- LiveCoding->Compile();
161
- auto Result = MCPSuccess();
162
- Result->SetStringField(TEXT("message"), TEXT("Live Coding compile triggered"));
163
- return MCPResult(Result);
164
- }
165
- else
166
- #endif
167
- {
168
- // Live Coding not available (or not on Windows) - fall back to console command
169
- UWorld* World = GetEditorWorld();
170
- if (World)
171
- {
172
- UKismetSystemLibrary::ExecuteConsoleCommand(World, TEXT("LiveCoding.Compile"), nullptr);
173
- auto Result = MCPSuccess();
174
- Result->SetStringField(TEXT("message"), TEXT("Hot reload triggered via console command (Live Coding module not active in session)"));
175
- return MCPResult(Result);
176
- }
177
- else
178
- {
179
- return MCPError(TEXT("Neither Live Coding module nor editor world available for hot reload"));
180
- }
181
- }
182
- }
183
-
184
-
185
- TSharedPtr<FJsonValue> FEditorHandlers::BuildGeometry(const TSharedPtr<FJsonObject>& Params)
186
- {
187
- REQUIRE_EDITOR_WORLD(World);
188
-
189
- GEditor->Exec(World, TEXT("MAP REBUILD"));
190
-
191
- auto Result = MCPSuccess();
192
- Result->SetStringField(TEXT("message"), TEXT("Geometry rebuild triggered"));
193
- return MCPResult(Result);
194
- }
195
-
196
-
197
- TSharedPtr<FJsonValue> FEditorHandlers::BuildHlod(const TSharedPtr<FJsonObject>& Params)
198
- {
199
- REQUIRE_EDITOR_WORLD(World);
200
-
201
- GEditor->Exec(World, TEXT("BuildHLOD"));
202
-
203
- auto Result = MCPSuccess();
204
- Result->SetStringField(TEXT("message"), TEXT("HLOD build triggered"));
205
- return MCPResult(Result);
206
- }
207
-
208
-
209
- // #14: Build project via UnrealBuildTool
210
- TSharedPtr<FJsonValue> FEditorHandlers::BuildProject(const TSharedPtr<FJsonObject>& Params)
211
- {
212
- if (!GEditor)
213
- {
214
- return MCPError(TEXT("Editor not available"));
215
- }
216
-
217
- FString Configuration = OptionalString(Params, TEXT("configuration"), TEXT("Development"));
218
- FString Platform = OptionalString(Params, TEXT("platform"), TEXT("Win64"));
219
- bool bClean = OptionalBool(Params, TEXT("clean"), false);
220
-
221
- // Build the project by invoking the engine's build tool
222
- // Use the project path from the running editor
223
- FString ProjectPath = FPaths::GetProjectFilePath();
224
- if (ProjectPath.IsEmpty())
225
- {
226
- return MCPError(TEXT("No project file path available"));
227
- }
228
-
229
- // Find UnrealBuildTool
230
- FString EngineDir = FPaths::EngineDir();
231
- FString UBTPath;
232
-
233
- #if PLATFORM_WINDOWS
234
- UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool"), TEXT("UnrealBuildTool.exe"));
235
- if (!FPaths::FileExists(UBTPath))
236
- {
237
- // Try legacy path
238
- UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool.exe"));
239
- }
240
- #else
241
- UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool"), TEXT("UnrealBuildTool"));
242
- #endif
243
-
244
- if (!FPaths::FileExists(UBTPath))
245
- {
246
- return MCPError(FString::Printf(TEXT("UnrealBuildTool not found at '%s'"), *UBTPath));
247
- }
248
-
249
- // Build the command line
250
- FString ProjectName = FPaths::GetBaseFilename(ProjectPath);
251
- FString Args = FString::Printf(
252
- TEXT("%sEditor %s %s -Project=\"%s\" -WaitMutex -FromMsBuild"),
253
- *ProjectName, *Platform, *Configuration, *ProjectPath);
254
-
255
- if (bClean)
256
- {
257
- Args += TEXT(" -Clean");
258
- }
259
-
260
- // Launch the process asynchronously
261
- FProcHandle ProcHandle = FPlatformProcess::CreateProc(
262
- *UBTPath, *Args, true, false, false, nullptr, 0, nullptr, nullptr);
263
-
264
- if (!ProcHandle.IsValid())
265
- {
266
- return MCPError(TEXT("Failed to launch UnrealBuildTool"));
267
- }
268
-
269
- auto Result = MCPSuccess();
270
- Result->SetStringField(TEXT("ubtPath"), UBTPath);
271
- Result->SetStringField(TEXT("args"), Args);
272
- Result->SetStringField(TEXT("configuration"), Configuration);
273
- Result->SetStringField(TEXT("platform"), Platform);
274
- Result->SetStringField(TEXT("note"), TEXT("Build launched asynchronously. Check output log for progress."));
275
- return MCPResult(Result);
276
- }
277
-
278
- // #49: Generate VS project files
279
-
280
-
281
- // #49: Generate VS project files
282
- TSharedPtr<FJsonValue> FEditorHandlers::GenerateProjectFiles(const TSharedPtr<FJsonObject>& Params)
283
- {
284
- FString ProjectPath = FPaths::GetProjectFilePath();
285
- if (ProjectPath.IsEmpty())
286
- {
287
- return MCPError(TEXT("No project file path available"));
288
- }
289
-
290
- // Find the GenerateProjectFiles script
291
- FString EngineDir = FPaths::EngineDir();
292
- FString ScriptPath;
293
- #if PLATFORM_WINDOWS
294
- ScriptPath = FPaths::Combine(EngineDir, TEXT("Build"), TEXT("BatchFiles"), TEXT("GenerateProjectFiles.bat"));
295
- #elif PLATFORM_MAC
296
- ScriptPath = FPaths::Combine(EngineDir, TEXT("Build"), TEXT("BatchFiles"), TEXT("Mac"), TEXT("GenerateProjectFiles.sh"));
297
- #else
298
- ScriptPath = FPaths::Combine(EngineDir, TEXT("Build"), TEXT("BatchFiles"), TEXT("Linux"), TEXT("GenerateProjectFiles.sh"));
299
- #endif
300
-
301
- if (!FPaths::FileExists(ScriptPath))
302
- {
303
- // Alternative: use UnrealBuildTool directly with -projectfiles flag
304
- FString UBTPath;
305
- #if PLATFORM_WINDOWS
306
- UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool"), TEXT("UnrealBuildTool.exe"));
307
- if (!FPaths::FileExists(UBTPath))
308
- {
309
- UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool.exe"));
310
- }
311
- #else
312
- UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool"), TEXT("UnrealBuildTool"));
313
- #endif
314
- if (!FPaths::FileExists(UBTPath))
315
- {
316
- return MCPError(TEXT("Neither GenerateProjectFiles script nor UnrealBuildTool found"));
317
- }
318
-
319
- FString Args = FString::Printf(TEXT("-projectfiles -project=\"%s\" -game -rocket -progress"), *ProjectPath);
320
- FProcHandle ProcHandle = FPlatformProcess::CreateProc(
321
- *UBTPath, *Args, true, false, false, nullptr, 0, nullptr, nullptr);
322
-
323
- if (!ProcHandle.IsValid())
324
- {
325
- return MCPError(TEXT("Failed to launch UnrealBuildTool for project file generation"));
326
- }
327
-
328
- auto Result = MCPSuccess();
329
- Result->SetStringField(TEXT("tool"), UBTPath);
330
- Result->SetStringField(TEXT("args"), Args);
331
- Result->SetStringField(TEXT("projectPath"), ProjectPath);
332
- Result->SetStringField(TEXT("note"), TEXT("Project file generation launched. Check output log for progress."));
333
- return MCPResult(Result);
334
- }
335
- else
336
- {
337
- FString Args = FString::Printf(TEXT("-project=\"%s\" -game"), *ProjectPath);
338
- FProcHandle ProcHandle = FPlatformProcess::CreateProc(
339
- *ScriptPath, *Args, true, false, false, nullptr, 0, nullptr, nullptr);
340
-
341
- if (!ProcHandle.IsValid())
342
- {
343
- return MCPError(TEXT("Failed to launch GenerateProjectFiles"));
344
- }
345
-
346
- auto Result = MCPSuccess();
347
- Result->SetStringField(TEXT("tool"), ScriptPath);
348
- Result->SetStringField(TEXT("args"), Args);
349
- Result->SetStringField(TEXT("projectPath"), ProjectPath);
350
- Result->SetStringField(TEXT("note"), TEXT("Project file generation launched. Check output log for progress."));
351
- return MCPResult(Result);
352
- }
353
- }
1
+ // Split from EditorHandlers.cpp to keep that file under 3k lines.
2
+ // All functions below are still members of FEditorHandlers - this file is a
3
+ // translation-unit partition, not a new class. Handler registration
4
+ // stays in EditorHandlers.cpp::RegisterHandlers.
5
+
6
+ #include "EditorHandlers.h"
7
+ #include "HandlerRegistry.h"
8
+ #include "HandlerUtils.h"
9
+ #include "Editor.h"
10
+ #include "Editor/EditorEngine.h"
11
+ #include "FileHelpers.h"
12
+ #include "Engine/World.h"
13
+ #include "Engine/Engine.h"
14
+ #include "GameFramework/Actor.h"
15
+ #include "Misc/Paths.h"
16
+ #include "Misc/FileHelper.h"
17
+ #include "Misc/CommandLine.h"
18
+ #include "HAL/PlatformProcess.h"
19
+ #include "HAL/PlatformFileManager.h"
20
+ #include "HAL/PlatformFile.h"
21
+ #include "Modules/ModuleManager.h"
22
+ #if PLATFORM_WINDOWS
23
+ #include "ILiveCodingModule.h"
24
+ #endif
25
+ #include "Kismet/KismetSystemLibrary.h"
26
+ #include "EditorValidatorSubsystem.h"
27
+ #include "Dom/JsonObject.h"
28
+ #include "Dom/JsonValue.h"
29
+
30
+ TSharedPtr<FJsonValue> FEditorHandlers::BuildLighting(const TSharedPtr<FJsonObject>& Params)
31
+ {
32
+ REQUIRE_EDITOR_WORLD(World);
33
+
34
+ FString Quality = OptionalString(Params, TEXT("quality"), TEXT("Preview"));
35
+
36
+ // Map quality string to console command
37
+ FString Command;
38
+ if (Quality == TEXT("Preview"))
39
+ {
40
+ Command = TEXT("BUILD LIGHTING QUALITY=Preview");
41
+ }
42
+ else if (Quality == TEXT("Medium"))
43
+ {
44
+ Command = TEXT("BUILD LIGHTING QUALITY=Medium");
45
+ }
46
+ else if (Quality == TEXT("High"))
47
+ {
48
+ Command = TEXT("BUILD LIGHTING QUALITY=High");
49
+ }
50
+ else if (Quality == TEXT("Production"))
51
+ {
52
+ Command = TEXT("BUILD LIGHTING QUALITY=Production");
53
+ }
54
+ else
55
+ {
56
+ Command = TEXT("BUILD LIGHTING QUALITY=Preview");
57
+ }
58
+
59
+ UKismetSystemLibrary::ExecuteConsoleCommand(World, Command, nullptr);
60
+
61
+ auto Result = MCPSuccess();
62
+ Result->SetStringField(TEXT("quality"), Quality);
63
+ Result->SetStringField(TEXT("command"), Command);
64
+ Result->SetStringField(TEXT("message"), FString::Printf(TEXT("Lighting build triggered (%s)"), *Quality));
65
+ return MCPResult(Result);
66
+ }
67
+
68
+
69
+ TSharedPtr<FJsonValue> FEditorHandlers::BuildAll(const TSharedPtr<FJsonObject>& Params)
70
+ {
71
+ REQUIRE_EDITOR_WORLD(World);
72
+
73
+ // Execute full build: geometry, lighting, and paths
74
+ UKismetSystemLibrary::ExecuteConsoleCommand(World, TEXT("MAP REBUILD"), nullptr);
75
+ UKismetSystemLibrary::ExecuteConsoleCommand(World, TEXT("BUILD LIGHTING"), nullptr);
76
+ UKismetSystemLibrary::ExecuteConsoleCommand(World, TEXT("RebuildNavigation"), nullptr);
77
+
78
+ auto Result = MCPSuccess();
79
+ Result->SetStringField(TEXT("message"), TEXT("Build All triggered (geometry + lighting + navigation)"));
80
+ return MCPResult(Result);
81
+ }
82
+
83
+
84
+ TSharedPtr<FJsonValue> FEditorHandlers::ValidateAssets(const TSharedPtr<FJsonObject>& Params)
85
+ {
86
+ FString Directory = OptionalString(Params, TEXT("directory"), TEXT("/Game/"));
87
+
88
+ // Try to use the EditorValidatorSubsystem if available
89
+ UEditorValidatorSubsystem* ValidatorSubsystem = GEditor ? GEditor->GetEditorSubsystem<UEditorValidatorSubsystem>() : nullptr;
90
+
91
+ if (ValidatorSubsystem)
92
+ {
93
+ // Use the DataValidation console command for broad validation
94
+ if (GEditor && GEditor->GetEditorWorldContext().World())
95
+ {
96
+ FString Command = FString::Printf(TEXT("DataValidation.ValidateAssets %s"), *Directory);
97
+ UKismetSystemLibrary::ExecuteConsoleCommand(
98
+ GEditor->GetEditorWorldContext().World(),
99
+ Command,
100
+ nullptr
101
+ );
102
+ }
103
+
104
+ auto Result = MCPSuccess();
105
+ Result->SetStringField(TEXT("directory"), Directory);
106
+ Result->SetStringField(TEXT("message"), TEXT("Asset validation triggered via EditorValidatorSubsystem"));
107
+ return MCPResult(Result);
108
+ }
109
+ else
110
+ {
111
+ // Fallback: trigger via console command
112
+ if (GEditor && GEditor->GetEditorWorldContext().World())
113
+ {
114
+ UKismetSystemLibrary::ExecuteConsoleCommand(
115
+ GEditor->GetEditorWorldContext().World(),
116
+ TEXT("DataValidation.ValidateAssets"),
117
+ nullptr
118
+ );
119
+ }
120
+
121
+ auto Result = MCPSuccess();
122
+ Result->SetStringField(TEXT("directory"), Directory);
123
+ Result->SetStringField(TEXT("message"), TEXT("Asset validation triggered via console command"));
124
+ return MCPResult(Result);
125
+ }
126
+ }
127
+
128
+
129
+ TSharedPtr<FJsonValue> FEditorHandlers::CookContent(const TSharedPtr<FJsonObject>& Params)
130
+ {
131
+ REQUIRE_EDITOR_WORLD(World);
132
+
133
+ FString Platform = OptionalString(Params, TEXT("platform"), TEXT("Windows"));
134
+
135
+ FString Command = FString::Printf(TEXT("CookOnTheFly -TargetPlatform=%s"), *Platform);
136
+ UKismetSystemLibrary::ExecuteConsoleCommand(World, Command, nullptr);
137
+
138
+ auto Result = MCPSuccess();
139
+ Result->SetStringField(TEXT("platform"), Platform);
140
+ Result->SetStringField(TEXT("command"), Command);
141
+ Result->SetStringField(TEXT("message"), FString::Printf(TEXT("Cook triggered for %s"), *Platform));
142
+ return MCPResult(Result);
143
+ }
144
+
145
+
146
+ TSharedPtr<FJsonValue> FEditorHandlers::HotReload(const TSharedPtr<FJsonObject>& Params)
147
+ {
148
+ #if PLATFORM_WINDOWS
149
+ ILiveCodingModule* LiveCoding = FModuleManager::GetModulePtr<ILiveCodingModule>(LIVE_CODING_MODULE_NAME);
150
+ if (LiveCoding && LiveCoding->IsEnabledForSession())
151
+ {
152
+ if (LiveCoding->IsCompiling())
153
+ {
154
+ auto Result = MCPSuccess();
155
+ Result->SetStringField(TEXT("message"), TEXT("Live Coding compile already in progress"));
156
+ return MCPResult(Result);
157
+ }
158
+
159
+ LiveCoding->EnableByDefault(true);
160
+ LiveCoding->Compile();
161
+ auto Result = MCPSuccess();
162
+ Result->SetStringField(TEXT("message"), TEXT("Live Coding compile triggered"));
163
+ return MCPResult(Result);
164
+ }
165
+ else
166
+ #endif
167
+ {
168
+ // Live Coding not available (or not on Windows) - fall back to console command
169
+ UWorld* World = GetEditorWorld();
170
+ if (World)
171
+ {
172
+ UKismetSystemLibrary::ExecuteConsoleCommand(World, TEXT("LiveCoding.Compile"), nullptr);
173
+ auto Result = MCPSuccess();
174
+ Result->SetStringField(TEXT("message"), TEXT("Hot reload triggered via console command (Live Coding module not active in session)"));
175
+ return MCPResult(Result);
176
+ }
177
+ else
178
+ {
179
+ return MCPError(TEXT("Neither Live Coding module nor editor world available for hot reload"));
180
+ }
181
+ }
182
+ }
183
+
184
+
185
+ TSharedPtr<FJsonValue> FEditorHandlers::BuildGeometry(const TSharedPtr<FJsonObject>& Params)
186
+ {
187
+ REQUIRE_EDITOR_WORLD(World);
188
+
189
+ GEditor->Exec(World, TEXT("MAP REBUILD"));
190
+
191
+ auto Result = MCPSuccess();
192
+ Result->SetStringField(TEXT("message"), TEXT("Geometry rebuild triggered"));
193
+ return MCPResult(Result);
194
+ }
195
+
196
+
197
+ TSharedPtr<FJsonValue> FEditorHandlers::BuildHlod(const TSharedPtr<FJsonObject>& Params)
198
+ {
199
+ REQUIRE_EDITOR_WORLD(World);
200
+
201
+ GEditor->Exec(World, TEXT("BuildHLOD"));
202
+
203
+ auto Result = MCPSuccess();
204
+ Result->SetStringField(TEXT("message"), TEXT("HLOD build triggered"));
205
+ return MCPResult(Result);
206
+ }
207
+
208
+
209
+ // #14: Build project via UnrealBuildTool
210
+ TSharedPtr<FJsonValue> FEditorHandlers::BuildProject(const TSharedPtr<FJsonObject>& Params)
211
+ {
212
+ if (!GEditor)
213
+ {
214
+ return MCPError(TEXT("Editor not available"));
215
+ }
216
+
217
+ FString Configuration = OptionalString(Params, TEXT("configuration"), TEXT("Development"));
218
+ FString Platform = OptionalString(Params, TEXT("platform"), TEXT("Win64"));
219
+ bool bClean = OptionalBool(Params, TEXT("clean"), false);
220
+
221
+ // Build the project by invoking the engine's build tool
222
+ // Use the project path from the running editor
223
+ FString ProjectPath = FPaths::GetProjectFilePath();
224
+ if (ProjectPath.IsEmpty())
225
+ {
226
+ return MCPError(TEXT("No project file path available"));
227
+ }
228
+
229
+ // Find UnrealBuildTool
230
+ FString EngineDir = FPaths::EngineDir();
231
+ FString UBTPath;
232
+
233
+ #if PLATFORM_WINDOWS
234
+ UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool"), TEXT("UnrealBuildTool.exe"));
235
+ if (!FPaths::FileExists(UBTPath))
236
+ {
237
+ // Try legacy path
238
+ UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool.exe"));
239
+ }
240
+ #else
241
+ UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool"), TEXT("UnrealBuildTool"));
242
+ #endif
243
+
244
+ if (!FPaths::FileExists(UBTPath))
245
+ {
246
+ return MCPError(FString::Printf(TEXT("UnrealBuildTool not found at '%s'"), *UBTPath));
247
+ }
248
+
249
+ // Build the command line
250
+ FString ProjectName = FPaths::GetBaseFilename(ProjectPath);
251
+ FString Args = FString::Printf(
252
+ TEXT("%sEditor %s %s -Project=\"%s\" -WaitMutex -FromMsBuild"),
253
+ *ProjectName, *Platform, *Configuration, *ProjectPath);
254
+
255
+ if (bClean)
256
+ {
257
+ Args += TEXT(" -Clean");
258
+ }
259
+
260
+ // Launch the process asynchronously
261
+ FProcHandle ProcHandle = FPlatformProcess::CreateProc(
262
+ *UBTPath, *Args, true, false, false, nullptr, 0, nullptr, nullptr);
263
+
264
+ if (!ProcHandle.IsValid())
265
+ {
266
+ return MCPError(TEXT("Failed to launch UnrealBuildTool"));
267
+ }
268
+
269
+ auto Result = MCPSuccess();
270
+ Result->SetStringField(TEXT("ubtPath"), UBTPath);
271
+ Result->SetStringField(TEXT("args"), Args);
272
+ Result->SetStringField(TEXT("configuration"), Configuration);
273
+ Result->SetStringField(TEXT("platform"), Platform);
274
+ Result->SetStringField(TEXT("note"), TEXT("Build launched asynchronously. Check output log for progress."));
275
+ return MCPResult(Result);
276
+ }
277
+
278
+ // #49: Generate VS project files
279
+
280
+
281
+ // #49: Generate VS project files
282
+ TSharedPtr<FJsonValue> FEditorHandlers::GenerateProjectFiles(const TSharedPtr<FJsonObject>& Params)
283
+ {
284
+ FString ProjectPath = FPaths::GetProjectFilePath();
285
+ if (ProjectPath.IsEmpty())
286
+ {
287
+ return MCPError(TEXT("No project file path available"));
288
+ }
289
+
290
+ // Find the GenerateProjectFiles script
291
+ FString EngineDir = FPaths::EngineDir();
292
+ FString ScriptPath;
293
+ #if PLATFORM_WINDOWS
294
+ ScriptPath = FPaths::Combine(EngineDir, TEXT("Build"), TEXT("BatchFiles"), TEXT("GenerateProjectFiles.bat"));
295
+ #elif PLATFORM_MAC
296
+ ScriptPath = FPaths::Combine(EngineDir, TEXT("Build"), TEXT("BatchFiles"), TEXT("Mac"), TEXT("GenerateProjectFiles.sh"));
297
+ #else
298
+ ScriptPath = FPaths::Combine(EngineDir, TEXT("Build"), TEXT("BatchFiles"), TEXT("Linux"), TEXT("GenerateProjectFiles.sh"));
299
+ #endif
300
+
301
+ if (!FPaths::FileExists(ScriptPath))
302
+ {
303
+ // Alternative: use UnrealBuildTool directly with -projectfiles flag
304
+ FString UBTPath;
305
+ #if PLATFORM_WINDOWS
306
+ UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool"), TEXT("UnrealBuildTool.exe"));
307
+ if (!FPaths::FileExists(UBTPath))
308
+ {
309
+ UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool.exe"));
310
+ }
311
+ #else
312
+ UBTPath = FPaths::Combine(EngineDir, TEXT("Binaries"), TEXT("DotNET"), TEXT("UnrealBuildTool"), TEXT("UnrealBuildTool"));
313
+ #endif
314
+ if (!FPaths::FileExists(UBTPath))
315
+ {
316
+ return MCPError(TEXT("Neither GenerateProjectFiles script nor UnrealBuildTool found"));
317
+ }
318
+
319
+ FString Args = FString::Printf(TEXT("-projectfiles -project=\"%s\" -game -rocket -progress"), *ProjectPath);
320
+ FProcHandle ProcHandle = FPlatformProcess::CreateProc(
321
+ *UBTPath, *Args, true, false, false, nullptr, 0, nullptr, nullptr);
322
+
323
+ if (!ProcHandle.IsValid())
324
+ {
325
+ return MCPError(TEXT("Failed to launch UnrealBuildTool for project file generation"));
326
+ }
327
+
328
+ auto Result = MCPSuccess();
329
+ Result->SetStringField(TEXT("tool"), UBTPath);
330
+ Result->SetStringField(TEXT("args"), Args);
331
+ Result->SetStringField(TEXT("projectPath"), ProjectPath);
332
+ Result->SetStringField(TEXT("note"), TEXT("Project file generation launched. Check output log for progress."));
333
+ return MCPResult(Result);
334
+ }
335
+ else
336
+ {
337
+ FString Args = FString::Printf(TEXT("-project=\"%s\" -game"), *ProjectPath);
338
+ FProcHandle ProcHandle = FPlatformProcess::CreateProc(
339
+ *ScriptPath, *Args, true, false, false, nullptr, 0, nullptr, nullptr);
340
+
341
+ if (!ProcHandle.IsValid())
342
+ {
343
+ return MCPError(TEXT("Failed to launch GenerateProjectFiles"));
344
+ }
345
+
346
+ auto Result = MCPSuccess();
347
+ Result->SetStringField(TEXT("tool"), ScriptPath);
348
+ Result->SetStringField(TEXT("args"), Args);
349
+ Result->SetStringField(TEXT("projectPath"), ProjectPath);
350
+ Result->SetStringField(TEXT("note"), TEXT("Project file generation launched. Check output log for progress."));
351
+ return MCPResult(Result);
352
+ }
353
+ }