fix(blueprint): resolve UClass lookups so non-trivial parent_class & component_type work - #26
Open
bwail wants to merge 1 commit into
Open
fix(blueprint): resolve UClass lookups so non-trivial parent_class & component_type work#26bwail wants to merge 1 commit into
bwail wants to merge 1 commit into
Conversation
…component_type work
Two longstanding bugs in HandleCreateBlueprint and HandleAddComponentToBlueprint
made the plugin silently incorrect for almost every input:
1. parent_class was effectively limited to Pawn/Actor.
The handler prepended an 'A' to the input then looked up
/Script/Engine.A<Name>. UE runtime UClass names do NOT carry the C++
A/U prefix — the actual path is /Script/Engine.Character, not .ACharacter.
So 'Character', and anything not in the hardcoded short-circuit, fell
back to AActor (with a warning logged about /Script/Engine.A<Name>
not existing).
2. component_type rejected every standard engine component.
FindObject<UClass>(nullptr, *ComponentType) with a bare name only
searches the transient package; engine components live in
/Script/Engine.*, so 'StaticMeshComponent', 'CameraComponent',
'PointLightComponent', 'BoxComponent' all returned 'Unknown component
type'. Adding a 'Component' suffix or stripping a 'U' prefix didn't
help because the underlying lookup was still scoped wrong.
Fix:
* Drop the A-prefix logic. Try /Script/Engine.<Bare>, /Script/Engine.A<Bare>,
and /Script/Game.* variants, then fall back to FindFirstObjectSafe<UClass>
(UE 5.1+) for plugin/module-defined classes. Validate Actor-derived.
* For components, replace FindObject(nullptr, ...) with FindFirstObjectSafe
plus a full-path fallback. Now bare names like 'Camera', 'StaticMesh',
'PointLight', 'Box', and full paths like '/Script/Engine.SkeletalMeshComponent'
all work. Strip leading C++-style 'U' if present.
Both copies of the file (UnrealMCP/Source and FlopperamUnrealMCP/Plugins/...)
are kept in sync as before.
Verified in UE 5.7 against a Character-derived BP with CameraComponent,
StaticMeshComponent, PointLightComponent — all parented and compiled cleanly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two longstanding bugs in
HandleCreateBlueprintandHandleAddComponentToBlueprint(inEpicUnrealMCPBlueprintCommands.cpp) made the plugin silently incorrect for nearly every input:Bug 1 —
parent_classwas effectively limited toPawn/ActorThe handler prepends an
Ato the input then looks up/Script/Engine.A<Name>. UE runtimeUClassnames do not carry the C++A/Uprefix — the actual path is/Script/Engine.Character, not/Script/Engine.ACharacter. Soparent_class="Character"(and anything not in the hardcoded short-circuit) silently fell back toAActor, with a warning logged about/Script/Engine.A<Name>not existing.Bug 2 —
component_typerejected every standard engine componentComponentClass = FindObject<UClass>(nullptr, *ComponentType);FindObject<UClass>(nullptr, BareName)only searches the transient package. Engine components live in/Script/Engine.*, soStaticMeshComponent,CameraComponent,PointLightComponent,BoxComponentall returnedUnknown component type. The existingComponent-suffix andU-prefix retries didn't help because the underlying lookup was still scoped wrong.Fix
A-prefix logic. Try/Script/Engine.<Bare>,/Script/Engine.A<Bare>, and the/Script/Game.*variants, then fall back toFindFirstObjectSafe<UClass>(UE 5.1+) for plugin/module-defined classes. Validate that the resolved class isActor-derived.FindObject(nullptr, ...)withFindFirstObjectSafe<UClass>plus a full-path fallback viaLoadObject<UClass>. Bare names likeCamera,StaticMesh,PointLight,Box, full paths like/Script/Engine.SkeletalMeshComponent, and C++-prefixedUCameraComponentall resolve. Strips a leadingUif the caller wrote it C++-style.Both copies of the file (
UnrealMCP/Source/...andFlopperamUnrealMCP/Plugins/UnrealMCP/Source/...) are kept in sync as before.Verification
Tested on UE 5.7 against a
Character-derived blueprint:create_blueprint(name="BP_FPSCharacter", parent_class="Character")→ parent now correctlyCharacter(wasActor)add_component_to_blueprint(component_type="CameraComponent", ...)→ ✅ (wasUnknown component type)add_component_to_blueprint(component_type="StaticMeshComponent", ...)→ ✅add_component_to_blueprint(component_type="PointLightComponent", ...)→ ✅add_component_to_blueprint(component_type="Box", ...)→ ✅ (resolves toBoxComponent)No changes outside the two
EpicUnrealMCPBlueprintCommands.cppcopies.