flockbay 0.10.19 → 0.10.21
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/dist/codex/flockbayMcpStdioBridge.cjs +8 -0
- package/dist/codex/flockbayMcpStdioBridge.mjs +8 -0
- package/dist/{index-BiUf5vLX.cjs → index-Bhkn02hu.cjs} +279 -38
- package/dist/{index-5jfGXWTy.mjs → index-By332wvJ.mjs} +279 -38
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.mjs +1 -1
- package/dist/{runCodex-Bh3-ebwT.cjs → runCodex-CH4lz1QX.cjs} +9 -5
- package/dist/{runCodex-DwsaTF4s.mjs → runCodex-d2KQX2mn.mjs} +9 -5
- package/dist/{runGemini-qA5dD13X.mjs → runGemini-Cn0C7MS1.mjs} +101 -31
- package/dist/{runGemini-hXryGqFd.cjs → runGemini-DNSymY04.cjs} +101 -31
- package/dist/{types-CL_3YyS9.cjs → types-DeH24uWs.cjs} +2 -2
- package/dist/{types-BQvaA3sv.mjs → types-mXJc7o0P.mjs} +1 -1
- package/package.json +1 -1
- package/scripts/claude_version_utils.cjs +66 -12
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPCommandSchema.cpp +10 -0
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/Private/Commands/UnrealMCPEditorCommands.cpp +205 -13
- package/tools/unreal-mcp/upstream/MCPGameProject/Plugins/UnrealMCP/Source/UnrealMCP/UnrealMCP.Build.cs +1 -0
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
#include "Components/StaticMeshComponent.h"
|
|
28
28
|
#include "Materials/MaterialInterface.h"
|
|
29
29
|
#include "Sound/SoundWave.h"
|
|
30
|
+
#include "IImageWrapper.h"
|
|
31
|
+
#include "IImageWrapperModule.h"
|
|
30
32
|
#include "EditorSubsystem.h"
|
|
31
33
|
#include "Subsystems/EditorActorSubsystem.h"
|
|
32
34
|
#include "Engine/Blueprint.h"
|
|
@@ -49,6 +51,35 @@
|
|
|
49
51
|
#include "Engine/EngineTypes.h"
|
|
50
52
|
#include "GameFramework/PlayerController.h"
|
|
51
53
|
#include "Camera/PlayerCameraManager.h"
|
|
54
|
+
#include "Engine/LocalPlayer.h"
|
|
55
|
+
#include "Engine/SceneCapture2D.h"
|
|
56
|
+
#include "Components/SceneCaptureComponent2D.h"
|
|
57
|
+
#include "Engine/TextureRenderTarget2D.h"
|
|
58
|
+
|
|
59
|
+
static bool SavePngToFile(const FString& FilePath, int32 Width, int32 Height, const TArray<FColor>& Bitmap)
|
|
60
|
+
{
|
|
61
|
+
IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
|
|
62
|
+
TSharedPtr<IImageWrapper> Wrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::PNG);
|
|
63
|
+
if (!Wrapper.IsValid())
|
|
64
|
+
{
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!Wrapper->SetRaw(Bitmap.GetData(), Bitmap.Num() * sizeof(FColor), Width, Height, ERGBFormat::BGRA, 8))
|
|
69
|
+
{
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const TArray64<uint8>& Compressed = Wrapper->GetCompressed(100);
|
|
74
|
+
if (Compressed.Num() <= 0 || Compressed.Num() > MAX_int32)
|
|
75
|
+
{
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
TArray<uint8> Out;
|
|
80
|
+
Out.Append(Compressed.GetData(), static_cast<int32>(Compressed.Num()));
|
|
81
|
+
return FFileHelper::SaveArrayToFile(Out, *FilePath);
|
|
82
|
+
}
|
|
52
83
|
|
|
53
84
|
FUnrealMCPEditorCommands::FUnrealMCPEditorCommands()
|
|
54
85
|
{
|
|
@@ -215,7 +246,7 @@ TSharedPtr<FJsonObject> FUnrealMCPEditorCommands::HandleSaveAll(const TSharedPtr
|
|
|
215
246
|
}
|
|
216
247
|
|
|
217
248
|
TArray<UPackage*> DirtyBefore;
|
|
218
|
-
FEditorFileUtils::GetDirtyPackages(DirtyBefore
|
|
249
|
+
FEditorFileUtils::GetDirtyPackages(DirtyBefore);
|
|
219
250
|
|
|
220
251
|
TSet<FString> DirtyBeforeNames;
|
|
221
252
|
for (UPackage* Pkg : DirtyBefore)
|
|
@@ -235,7 +266,7 @@ TSharedPtr<FJsonObject> FUnrealMCPEditorCommands::HandleSaveAll(const TSharedPtr
|
|
|
235
266
|
);
|
|
236
267
|
|
|
237
268
|
TArray<UPackage*> DirtyAfter;
|
|
238
|
-
FEditorFileUtils::GetDirtyPackages(DirtyAfter
|
|
269
|
+
FEditorFileUtils::GetDirtyPackages(DirtyAfter);
|
|
239
270
|
|
|
240
271
|
TSet<FString> DirtyAfterNames;
|
|
241
272
|
for (UPackage* Pkg : DirtyAfter)
|
|
@@ -289,8 +320,7 @@ TSharedPtr<FJsonObject> FUnrealMCPEditorCommands::HandleSaveAll(const TSharedPtr
|
|
|
289
320
|
Details->SetArrayField(TEXT("stillDirtyPackages"), StillDirty);
|
|
290
321
|
|
|
291
322
|
TSharedPtr<FJsonObject> ErrObj = FUnrealMCPCommonUtils::CreateErrorResponse(
|
|
292
|
-
TEXT("Some packages are still dirty after save_all. They may require manual Save As, source control checkout, or have save errors. Resolve in-editor and retry save_all.")
|
|
293
|
-
);
|
|
323
|
+
TEXT("Some packages are still dirty after save_all. They may require manual Save As, source control checkout, or have save errors. Resolve in-editor and retry save_all."));
|
|
294
324
|
ErrObj->SetObjectField(TEXT("details"), Details);
|
|
295
325
|
return ErrObj;
|
|
296
326
|
}
|
|
@@ -2295,26 +2325,188 @@ TSharedPtr<FJsonObject> FUnrealMCPEditorCommands::HandleTakeScreenshot(const TSh
|
|
|
2295
2325
|
FilePath += TEXT(".png");
|
|
2296
2326
|
}
|
|
2297
2327
|
|
|
2298
|
-
|
|
2328
|
+
FString Source = TEXT("auto");
|
|
2329
|
+
if (Params->TryGetStringField(TEXT("source"), Source))
|
|
2330
|
+
{
|
|
2331
|
+
Source = Source.TrimStartAndEnd().ToLower();
|
|
2332
|
+
if (Source.IsEmpty())
|
|
2333
|
+
{
|
|
2334
|
+
Source = TEXT("auto");
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
double WidthNum = 0.0;
|
|
2339
|
+
double HeightNum = 0.0;
|
|
2340
|
+
int32 RequestedWidth = 0;
|
|
2341
|
+
int32 RequestedHeight = 0;
|
|
2342
|
+
if (Params->TryGetNumberField(TEXT("width"), WidthNum))
|
|
2343
|
+
{
|
|
2344
|
+
RequestedWidth = static_cast<int32>(WidthNum);
|
|
2345
|
+
}
|
|
2346
|
+
else if (Params->TryGetNumberField(TEXT("resX"), WidthNum))
|
|
2347
|
+
{
|
|
2348
|
+
RequestedWidth = static_cast<int32>(WidthNum);
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
if (Params->TryGetNumberField(TEXT("height"), HeightNum))
|
|
2352
|
+
{
|
|
2353
|
+
RequestedHeight = static_cast<int32>(HeightNum);
|
|
2354
|
+
}
|
|
2355
|
+
else if (Params->TryGetNumberField(TEXT("resY"), HeightNum))
|
|
2356
|
+
{
|
|
2357
|
+
RequestedHeight = static_cast<int32>(HeightNum);
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
const bool bPieRunning = (GEditor && GEditor->PlayWorld);
|
|
2361
|
+
const bool bWantsPie = (Source == TEXT("pie"));
|
|
2362
|
+
const bool bWantsEditor = (Source == TEXT("editor"));
|
|
2363
|
+
const bool bAuto = (Source == TEXT("auto"));
|
|
2364
|
+
if (!bWantsPie && !bWantsEditor && !bAuto)
|
|
2365
|
+
{
|
|
2366
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(FString::Printf(TEXT("Invalid screenshot source: %s (expected: auto|pie|editor)"), *Source));
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
const bool bUsePieCapture = bWantsPie || (bAuto && bPieRunning);
|
|
2370
|
+
if (bUsePieCapture)
|
|
2371
|
+
{
|
|
2372
|
+
if (!bPieRunning)
|
|
2373
|
+
{
|
|
2374
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("PIE is not running (PlayWorld is null)."));
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
UWorld* PlayWorld = GEditor->PlayWorld;
|
|
2378
|
+
APlayerController* PC = PlayWorld ? PlayWorld->GetFirstPlayerController() : nullptr;
|
|
2379
|
+
if (!PC)
|
|
2380
|
+
{
|
|
2381
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to find PlayerController in PlayWorld."));
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
APlayerCameraManager* PCM = PC->PlayerCameraManager;
|
|
2385
|
+
if (!PCM)
|
|
2386
|
+
{
|
|
2387
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to find PlayerCameraManager (PlayerController.PlayerCameraManager is null)."));
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
int32 Width = RequestedWidth;
|
|
2391
|
+
int32 Height = RequestedHeight;
|
|
2392
|
+
if (Width <= 0 || Height <= 0)
|
|
2393
|
+
{
|
|
2394
|
+
if (ULocalPlayer* LocalPlayer = PC->GetLocalPlayer())
|
|
2395
|
+
{
|
|
2396
|
+
if (LocalPlayer->ViewportClient && LocalPlayer->ViewportClient->Viewport)
|
|
2397
|
+
{
|
|
2398
|
+
const FIntPoint ViewSize = LocalPlayer->ViewportClient->Viewport->GetSizeXY();
|
|
2399
|
+
if (ViewSize.X > 0 && ViewSize.Y > 0)
|
|
2400
|
+
{
|
|
2401
|
+
if (Width <= 0)
|
|
2402
|
+
{
|
|
2403
|
+
Width = ViewSize.X;
|
|
2404
|
+
}
|
|
2405
|
+
if (Height <= 0)
|
|
2406
|
+
{
|
|
2407
|
+
Height = ViewSize.Y;
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
if (Width <= 0 || Height <= 0)
|
|
2415
|
+
{
|
|
2416
|
+
Width = 1280;
|
|
2417
|
+
Height = 720;
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
const FVector CamLocation = PCM->GetCameraLocation();
|
|
2421
|
+
const FRotator CamRotation = PCM->GetCameraRotation();
|
|
2422
|
+
|
|
2423
|
+
FActorSpawnParameters SpawnParams;
|
|
2424
|
+
SpawnParams.ObjectFlags |= RF_Transient;
|
|
2425
|
+
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
|
2426
|
+
|
|
2427
|
+
ASceneCapture2D* CaptureActor = PlayWorld->SpawnActor<ASceneCapture2D>(ASceneCapture2D::StaticClass(), CamLocation, CamRotation, SpawnParams);
|
|
2428
|
+
if (!CaptureActor)
|
|
2429
|
+
{
|
|
2430
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to spawn ASceneCapture2D for PIE screenshot capture."));
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
USceneCaptureComponent2D* CaptureComp = CaptureActor->GetCaptureComponent2D();
|
|
2434
|
+
if (!CaptureComp)
|
|
2435
|
+
{
|
|
2436
|
+
CaptureActor->Destroy();
|
|
2437
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to get SceneCaptureComponent2D from ASceneCapture2D."));
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
UTextureRenderTarget2D* RenderTarget = NewObject<UTextureRenderTarget2D>(CaptureComp);
|
|
2441
|
+
if (!RenderTarget)
|
|
2442
|
+
{
|
|
2443
|
+
CaptureActor->Destroy();
|
|
2444
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to create UTextureRenderTarget2D."));
|
|
2445
|
+
}
|
|
2446
|
+
RenderTarget->InitCustomFormat(Width, Height, PF_B8G8R8A8, /*bForceLinearGamma*/ false);
|
|
2447
|
+
RenderTarget->ClearColor = FLinearColor::Black;
|
|
2448
|
+
RenderTarget->UpdateResourceImmediate(true);
|
|
2449
|
+
|
|
2450
|
+
CaptureComp->TextureTarget = RenderTarget;
|
|
2451
|
+
CaptureComp->bCaptureEveryFrame = false;
|
|
2452
|
+
CaptureComp->bCaptureOnMovement = false;
|
|
2453
|
+
CaptureComp->CaptureSource = ESceneCaptureSource::SCS_FinalColorLDR;
|
|
2454
|
+
CaptureComp->FOVAngle = PCM->GetFOVAngle();
|
|
2455
|
+
|
|
2456
|
+
CaptureComp->CaptureScene();
|
|
2457
|
+
|
|
2458
|
+
FTextureRenderTargetResource* RenderResource = RenderTarget->GameThread_GetRenderTargetResource();
|
|
2459
|
+
if (!RenderResource)
|
|
2460
|
+
{
|
|
2461
|
+
CaptureActor->Destroy();
|
|
2462
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to get render target resource for PIE screenshot capture."));
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
TArray<FColor> Bitmap;
|
|
2466
|
+
if (!RenderResource->ReadPixels(Bitmap))
|
|
2467
|
+
{
|
|
2468
|
+
CaptureActor->Destroy();
|
|
2469
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to read pixels from PIE render target."));
|
|
2470
|
+
}
|
|
2471
|
+
|
|
2472
|
+
CaptureActor->Destroy();
|
|
2473
|
+
|
|
2474
|
+
if (!SavePngToFile(FilePath, Width, Height, Bitmap))
|
|
2475
|
+
{
|
|
2476
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to save screenshot PNG to disk."));
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
2480
|
+
ResultObj->SetStringField(TEXT("filepath"), FilePath);
|
|
2481
|
+
ResultObj->SetStringField(TEXT("source"), TEXT("pie"));
|
|
2482
|
+
ResultObj->SetNumberField(TEXT("width"), Width);
|
|
2483
|
+
ResultObj->SetNumberField(TEXT("height"), Height);
|
|
2484
|
+
return ResultObj;
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
// Editor viewport screenshot (can be stale if the OS window is not focused; prefer PIE capture when playing).
|
|
2299
2488
|
if (GEditor && GEditor->GetActiveViewport())
|
|
2300
2489
|
{
|
|
2490
|
+
GEditor->RedrawAllViewports(/*bInvalidateHitProxies*/ true);
|
|
2491
|
+
|
|
2301
2492
|
FViewport* Viewport = GEditor->GetActiveViewport();
|
|
2493
|
+
const FIntPoint ViewSize = Viewport->GetSizeXY();
|
|
2302
2494
|
TArray<FColor> Bitmap;
|
|
2303
|
-
FIntRect ViewportRect(0, 0,
|
|
2304
|
-
|
|
2495
|
+
FIntRect ViewportRect(0, 0, ViewSize.X, ViewSize.Y);
|
|
2496
|
+
|
|
2305
2497
|
if (Viewport->ReadPixels(Bitmap, FReadSurfaceDataFlags(), ViewportRect))
|
|
2306
2498
|
{
|
|
2307
|
-
|
|
2308
|
-
FImageUtils::CompressImageArray(Viewport->GetSizeXY().X, Viewport->GetSizeXY().Y, Bitmap, CompressedBitmap);
|
|
2309
|
-
|
|
2310
|
-
if (FFileHelper::SaveArrayToFile(CompressedBitmap, *FilePath))
|
|
2499
|
+
if (SavePngToFile(FilePath, ViewSize.X, ViewSize.Y, Bitmap))
|
|
2311
2500
|
{
|
|
2312
2501
|
TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
|
|
2313
2502
|
ResultObj->SetStringField(TEXT("filepath"), FilePath);
|
|
2503
|
+
ResultObj->SetStringField(TEXT("source"), TEXT("editor"));
|
|
2504
|
+
ResultObj->SetNumberField(TEXT("width"), ViewSize.X);
|
|
2505
|
+
ResultObj->SetNumberField(TEXT("height"), ViewSize.Y);
|
|
2314
2506
|
return ResultObj;
|
|
2315
2507
|
}
|
|
2316
2508
|
}
|
|
2317
2509
|
}
|
|
2318
|
-
|
|
2319
|
-
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to take screenshot"));
|
|
2510
|
+
|
|
2511
|
+
return FUnrealMCPCommonUtils::CreateErrorResponse(TEXT("Failed to take screenshot."));
|
|
2320
2512
|
}
|