ue-mcp 0.4.0-alpha

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 (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/dist/bridge.d.ts +25 -0
  4. package/dist/bridge.js +124 -0
  5. package/dist/bridge.js.map +1 -0
  6. package/dist/deployer.d.ts +18 -0
  7. package/dist/deployer.js +175 -0
  8. package/dist/deployer.js.map +1 -0
  9. package/dist/editor-control.d.ts +15 -0
  10. package/dist/editor-control.js +181 -0
  11. package/dist/editor-control.js.map +1 -0
  12. package/dist/github-app.d.ts +4 -0
  13. package/dist/github-app.js +94 -0
  14. package/dist/github-app.js.map +1 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +125 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/init.d.ts +2 -0
  19. package/dist/init.js +290 -0
  20. package/dist/init.js.map +1 -0
  21. package/dist/instructions.d.ts +1 -0
  22. package/dist/instructions.js +150 -0
  23. package/dist/instructions.js.map +1 -0
  24. package/dist/project.d.ts +32 -0
  25. package/dist/project.js +175 -0
  26. package/dist/project.js.map +1 -0
  27. package/dist/tools/animation.d.ts +2 -0
  28. package/dist/tools/animation.js +62 -0
  29. package/dist/tools/animation.js.map +1 -0
  30. package/dist/tools/asset.d.ts +2 -0
  31. package/dist/tools/asset.js +128 -0
  32. package/dist/tools/asset.js.map +1 -0
  33. package/dist/tools/audio.d.ts +2 -0
  34. package/dist/tools/audio.js +24 -0
  35. package/dist/tools/audio.js.map +1 -0
  36. package/dist/tools/blueprint.d.ts +2 -0
  37. package/dist/tools/blueprint.js +64 -0
  38. package/dist/tools/blueprint.js.map +1 -0
  39. package/dist/tools/demo.d.ts +2 -0
  40. package/dist/tools/demo.js +10 -0
  41. package/dist/tools/demo.js.map +1 -0
  42. package/dist/tools/editor.d.ts +2 -0
  43. package/dist/tools/editor.js +133 -0
  44. package/dist/tools/editor.js.map +1 -0
  45. package/dist/tools/feedback.d.ts +2 -0
  46. package/dist/tools/feedback.js +44 -0
  47. package/dist/tools/feedback.js.map +1 -0
  48. package/dist/tools/foliage.d.ts +2 -0
  49. package/dist/tools/foliage.js +29 -0
  50. package/dist/tools/foliage.js.map +1 -0
  51. package/dist/tools/gameplay.d.ts +2 -0
  52. package/dist/tools/gameplay.js +101 -0
  53. package/dist/tools/gameplay.js.map +1 -0
  54. package/dist/tools/gas.d.ts +2 -0
  55. package/dist/tools/gas.js +43 -0
  56. package/dist/tools/gas.js.map +1 -0
  57. package/dist/tools/landscape.d.ts +2 -0
  58. package/dist/tools/landscape.js +32 -0
  59. package/dist/tools/landscape.js.map +1 -0
  60. package/dist/tools/level.d.ts +2 -0
  61. package/dist/tools/level.js +66 -0
  62. package/dist/tools/level.js.map +1 -0
  63. package/dist/tools/material.d.ts +2 -0
  64. package/dist/tools/material.js +59 -0
  65. package/dist/tools/material.js.map +1 -0
  66. package/dist/tools/networking.d.ts +2 -0
  67. package/dist/tools/networking.js +42 -0
  68. package/dist/tools/networking.js.map +1 -0
  69. package/dist/tools/niagara.d.ts +2 -0
  70. package/dist/tools/niagara.js +42 -0
  71. package/dist/tools/niagara.js.map +1 -0
  72. package/dist/tools/pcg.d.ts +2 -0
  73. package/dist/tools/pcg.js +39 -0
  74. package/dist/tools/pcg.js.map +1 -0
  75. package/dist/tools/project.d.ts +2 -0
  76. package/dist/tools/project.js +282 -0
  77. package/dist/tools/project.js.map +1 -0
  78. package/dist/tools/reflection.d.ts +2 -0
  79. package/dist/tools/reflection.js +26 -0
  80. package/dist/tools/reflection.js.map +1 -0
  81. package/dist/tools/widget.d.ts +2 -0
  82. package/dist/tools/widget.js +34 -0
  83. package/dist/tools/widget.js.map +1 -0
  84. package/dist/types.d.ts +21 -0
  85. package/dist/types.js +38 -0
  86. package/dist/types.js.map +1 -0
  87. package/package.json +76 -0
  88. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.cpp +746 -0
  89. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/BridgeServer.h +81 -0
  90. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.cpp +49 -0
  91. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/GameThreadExecutor.h +37 -0
  92. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.cpp +75 -0
  93. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/HandlerRegistry.h +50 -0
  94. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.cpp +1418 -0
  95. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AnimationHandlers.h +43 -0
  96. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.cpp +1773 -0
  97. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AssetHandlers.h +48 -0
  98. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers.cpp +289 -0
  99. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/AudioHandlers.h +18 -0
  100. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.cpp +1982 -0
  101. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/BlueprintHandlers.h +44 -0
  102. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.cpp +1217 -0
  103. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DemoHandlers.h +71 -0
  104. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DialogHandlers.cpp +465 -0
  105. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/DialogHandlers.h +49 -0
  106. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.cpp +1676 -0
  107. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/EditorHandlers.h +53 -0
  108. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.cpp +876 -0
  109. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/FoliageHandlers.h +22 -0
  110. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.cpp +2222 -0
  111. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GameplayHandlers.h +54 -0
  112. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.cpp +783 -0
  113. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/GasHandlers.h +24 -0
  114. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.cpp +898 -0
  115. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LandscapeHandlers.h +24 -0
  116. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.cpp +1270 -0
  117. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/LevelHandlers.h +34 -0
  118. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.cpp +2190 -0
  119. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/MaterialHandlers.h +53 -0
  120. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.cpp +554 -0
  121. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NetworkingHandlers.h +29 -0
  122. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.cpp +601 -0
  123. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/NiagaraHandlers.h +25 -0
  124. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.cpp +1024 -0
  125. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PCGHandlers.h +25 -0
  126. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.cpp +370 -0
  127. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/PhysicsHandlers.h +19 -0
  128. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers.cpp +499 -0
  129. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/ReflectionHandlers.h +27 -0
  130. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.cpp +426 -0
  131. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SequencerHandlers.h +19 -0
  132. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.cpp +303 -0
  133. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/SplineHandlers.h +18 -0
  134. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.cpp +985 -0
  135. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/Handlers/WidgetHandlers.h +27 -0
  136. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/JsonSerializer.cpp +181 -0
  137. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/JsonSerializer.h +42 -0
  138. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Private/UE_MCP_Bridge.cpp +39 -0
  139. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/Public/UE_MCP_BridgeModule.h +14 -0
  140. package/plugin/ue_mcp_bridge/Source/UE_MCP_Bridge/UE_MCP_Bridge.Build.cs +87 -0
  141. package/plugin/ue_mcp_bridge/UE_MCP_Bridge.uplugin +55 -0
@@ -0,0 +1,499 @@
1
+ #include "ReflectionHandlers.h"
2
+ #include "HandlerRegistry.h"
3
+ #include "UObject/UObjectGlobals.h"
4
+ #include "UObject/Class.h"
5
+ #include "UObject/UnrealType.h"
6
+ #include "UObject/UObjectIterator.h"
7
+ #include "Engine/Engine.h"
8
+ #include "GameplayTagsManager.h"
9
+ #include "GameplayTagsSettings.h"
10
+ #include "GameplayTagContainer.h"
11
+ #include "Misc/ConfigCacheIni.h"
12
+ #include "Dom/JsonObject.h"
13
+ #include "Dom/JsonValue.h"
14
+ #include "JsonSerializer.h"
15
+ #include "HAL/PlatformFilemanager.h"
16
+ #include "Misc/FileHelper.h"
17
+ #include "Misc/Paths.h"
18
+
19
+ void FReflectionHandlers::RegisterHandlers(FMCPHandlerRegistry& Registry)
20
+ {
21
+ Registry.RegisterHandler(TEXT("reflect_class"), &ReflectClass);
22
+ Registry.RegisterHandler(TEXT("reflect_struct"), &ReflectStruct);
23
+ Registry.RegisterHandler(TEXT("reflect_enum"), &ReflectEnum);
24
+ Registry.RegisterHandler(TEXT("list_classes"), &ListClasses);
25
+ Registry.RegisterHandler(TEXT("list_gameplay_tags"), &ListGameplayTags);
26
+ Registry.RegisterHandler(TEXT("create_gameplay_tag"), &CreateGameplayTag);
27
+ }
28
+
29
+ TSharedPtr<FJsonValue> FReflectionHandlers::ReflectClass(const TSharedPtr<FJsonObject>& Params)
30
+ {
31
+ FString ClassName;
32
+ if (!Params->TryGetStringField(TEXT("className"), ClassName))
33
+ {
34
+ TSharedPtr<FJsonObject> Error = MakeShared<FJsonObject>();
35
+ Error->SetStringField(TEXT("error"), TEXT("className parameter required"));
36
+ return MakeShared<FJsonValueObject>(Error);
37
+ }
38
+
39
+ UClass* Class = FindClass(ClassName);
40
+ if (!Class)
41
+ {
42
+ TSharedPtr<FJsonObject> Error = MakeShared<FJsonObject>();
43
+ Error->SetStringField(TEXT("error"), FString::Printf(TEXT("Class not found: %s"), *ClassName));
44
+ return MakeShared<FJsonValueObject>(Error);
45
+ }
46
+
47
+ bool bIncludeInherited = false;
48
+ Params->TryGetBoolField(TEXT("includeInherited"), bIncludeInherited);
49
+
50
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
51
+ Result->SetStringField(TEXT("className"), Class->GetName());
52
+
53
+ if (Class->GetSuperClass())
54
+ {
55
+ Result->SetStringField(TEXT("parentClass"), Class->GetSuperClass()->GetName());
56
+ }
57
+
58
+ // Build parent chain
59
+ TArray<TSharedPtr<FJsonValue>> ParentChain;
60
+ UClass* Parent = Class->GetSuperClass();
61
+ while (Parent)
62
+ {
63
+ ParentChain.Add(MakeShared<FJsonValueString>(Parent->GetName()));
64
+ Parent = Parent->GetSuperClass();
65
+ }
66
+ Result->SetArrayField(TEXT("parentChain"), ParentChain);
67
+
68
+ Result->SetBoolField(TEXT("isAbstract"), Class->HasAnyClassFlags(CLASS_Abstract));
69
+
70
+ // Get properties
71
+ TArray<TSharedPtr<FJsonValue>> PropertiesArray;
72
+ for (TFieldIterator<FProperty> PropIt(Class, bIncludeInherited ? EFieldIteratorFlags::IncludeSuper : EFieldIteratorFlags::ExcludeSuper); PropIt; ++PropIt)
73
+ {
74
+ FProperty* Prop = *PropIt;
75
+ TSharedPtr<FJsonObject> PropObj = MakeShared<FJsonObject>();
76
+ PropObj->SetStringField(TEXT("name"), Prop->GetName());
77
+ PropObj->SetStringField(TEXT("type"), Prop->GetCPPType());
78
+ PropertiesArray.Add(MakeShared<FJsonValueObject>(PropObj));
79
+ }
80
+ Result->SetArrayField(TEXT("properties"), PropertiesArray);
81
+ Result->SetNumberField(TEXT("propertyCount"), PropertiesArray.Num());
82
+
83
+ // Get functions
84
+ TArray<TSharedPtr<FJsonValue>> FunctionsArray;
85
+ for (TFieldIterator<UFunction> FuncIt(Class, bIncludeInherited ? EFieldIteratorFlags::IncludeSuper : EFieldIteratorFlags::ExcludeSuper); FuncIt; ++FuncIt)
86
+ {
87
+ UFunction* Func = *FuncIt;
88
+ TSharedPtr<FJsonObject> FuncObj = MakeShared<FJsonObject>();
89
+ FuncObj->SetStringField(TEXT("name"), Func->GetName());
90
+ FunctionsArray.Add(MakeShared<FJsonValueObject>(FuncObj));
91
+ }
92
+ Result->SetArrayField(TEXT("functions"), FunctionsArray);
93
+ Result->SetNumberField(TEXT("functionCount"), FunctionsArray.Num());
94
+
95
+ return MakeShared<FJsonValueObject>(Result);
96
+ }
97
+
98
+ TSharedPtr<FJsonValue> FReflectionHandlers::ReflectStruct(const TSharedPtr<FJsonObject>& Params)
99
+ {
100
+ FString StructName;
101
+ if (!Params->TryGetStringField(TEXT("structName"), StructName))
102
+ {
103
+ TSharedPtr<FJsonObject> Error = MakeShared<FJsonObject>();
104
+ Error->SetStringField(TEXT("error"), TEXT("structName parameter required"));
105
+ return MakeShared<FJsonValueObject>(Error);
106
+ }
107
+
108
+ UScriptStruct* Struct = FindStruct(StructName);
109
+ if (!Struct)
110
+ {
111
+ TSharedPtr<FJsonObject> Error = MakeShared<FJsonObject>();
112
+ Error->SetStringField(TEXT("error"), FString::Printf(TEXT("Struct not found: %s"), *StructName));
113
+ return MakeShared<FJsonValueObject>(Error);
114
+ }
115
+
116
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
117
+ Result->SetStringField(TEXT("structName"), Struct->GetName());
118
+
119
+ TArray<TSharedPtr<FJsonValue>> FieldsArray;
120
+ for (TFieldIterator<FProperty> PropIt(Struct); PropIt; ++PropIt)
121
+ {
122
+ FProperty* Prop = *PropIt;
123
+ TSharedPtr<FJsonObject> FieldObj = MakeShared<FJsonObject>();
124
+ FieldObj->SetStringField(TEXT("name"), Prop->GetName());
125
+ FieldObj->SetStringField(TEXT("type"), Prop->GetCPPType());
126
+ FieldsArray.Add(MakeShared<FJsonValueObject>(FieldObj));
127
+ }
128
+ Result->SetArrayField(TEXT("fields"), FieldsArray);
129
+ Result->SetNumberField(TEXT("fieldCount"), FieldsArray.Num());
130
+
131
+ return MakeShared<FJsonValueObject>(Result);
132
+ }
133
+
134
+ TSharedPtr<FJsonValue> FReflectionHandlers::ReflectEnum(const TSharedPtr<FJsonObject>& Params)
135
+ {
136
+ FString EnumName;
137
+ if (!Params->TryGetStringField(TEXT("enumName"), EnumName))
138
+ {
139
+ TSharedPtr<FJsonObject> Error = MakeShared<FJsonObject>();
140
+ Error->SetStringField(TEXT("error"), TEXT("enumName parameter required"));
141
+ return MakeShared<FJsonValueObject>(Error);
142
+ }
143
+
144
+ UEnum* Enum = FindEnum(EnumName);
145
+ if (!Enum)
146
+ {
147
+ TSharedPtr<FJsonObject> Error = MakeShared<FJsonObject>();
148
+ Error->SetStringField(TEXT("error"), FString::Printf(TEXT("Enum not found: %s"), *EnumName));
149
+ return MakeShared<FJsonValueObject>(Error);
150
+ }
151
+
152
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
153
+ Result->SetStringField(TEXT("enumName"), Enum->GetName());
154
+
155
+ TArray<TSharedPtr<FJsonValue>> ValuesArray;
156
+ int32 NumEnums = Enum->NumEnums();
157
+ for (int32 i = 0; i < NumEnums - 1; ++i) // -1 to exclude _MAX
158
+ {
159
+ FString EnumNameStr = Enum->GetNameStringByIndex(i);
160
+ if (!EnumNameStr.IsEmpty() && !EnumNameStr.EndsWith(TEXT("_MAX")))
161
+ {
162
+ TSharedPtr<FJsonObject> ValueObj = MakeShared<FJsonObject>();
163
+ ValueObj->SetStringField(TEXT("name"), EnumNameStr);
164
+ ValueObj->SetNumberField(TEXT("value"), Enum->GetValueByIndex(i));
165
+ ValueObj->SetStringField(TEXT("displayName"), Enum->GetDisplayNameTextByIndex(i).ToString());
166
+ ValuesArray.Add(MakeShared<FJsonValueObject>(ValueObj));
167
+ }
168
+ }
169
+ Result->SetArrayField(TEXT("values"), ValuesArray);
170
+ Result->SetNumberField(TEXT("valueCount"), ValuesArray.Num());
171
+
172
+ return MakeShared<FJsonValueObject>(Result);
173
+ }
174
+
175
+ TSharedPtr<FJsonValue> FReflectionHandlers::ListClasses(const TSharedPtr<FJsonObject>& Params)
176
+ {
177
+ FString ParentFilter;
178
+ Params->TryGetStringField(TEXT("parentFilter"), ParentFilter);
179
+
180
+ int32 Limit = 100;
181
+ Params->TryGetNumberField(TEXT("limit"), Limit);
182
+
183
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
184
+
185
+ if (!ParentFilter.IsEmpty())
186
+ {
187
+ UClass* ParentClass = FindClass(ParentFilter);
188
+ if (!ParentClass)
189
+ {
190
+ Result->SetStringField(TEXT("error"), FString::Printf(TEXT("Parent class not found: %s"), *ParentFilter));
191
+ return MakeShared<FJsonValueObject>(Result);
192
+ }
193
+
194
+ TArray<TSharedPtr<FJsonValue>> ClassesArray;
195
+ for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt)
196
+ {
197
+ UClass* Class = *ClassIt;
198
+ if (Class && Class->IsChildOf(ParentClass))
199
+ {
200
+ TSharedPtr<FJsonObject> ClassObj = MakeShared<FJsonObject>();
201
+ ClassObj->SetStringField(TEXT("name"), Class->GetName());
202
+ if (Class->GetSuperClass())
203
+ {
204
+ ClassObj->SetStringField(TEXT("parent"), Class->GetSuperClass()->GetName());
205
+ }
206
+ ClassesArray.Add(MakeShared<FJsonValueObject>(ClassObj));
207
+ if (ClassesArray.Num() >= Limit)
208
+ {
209
+ break;
210
+ }
211
+ }
212
+ }
213
+ Result->SetStringField(TEXT("parentFilter"), ParentFilter);
214
+ Result->SetArrayField(TEXT("classes"), ClassesArray);
215
+ Result->SetNumberField(TEXT("count"), ClassesArray.Num());
216
+ }
217
+ else
218
+ {
219
+ // List common base classes
220
+ TArray<FString> CommonClasses = {
221
+ TEXT("Actor"), TEXT("Pawn"), TEXT("Character"), TEXT("PlayerController"), TEXT("GameModeBase"),
222
+ TEXT("GameStateBase"), TEXT("PlayerState"), TEXT("HUD"), TEXT("ActorComponent"),
223
+ TEXT("SceneComponent"), TEXT("PrimitiveComponent"), TEXT("StaticMeshComponent"),
224
+ TEXT("SkeletalMeshComponent"), TEXT("CameraComponent"), TEXT("AudioComponent"),
225
+ TEXT("LightComponent"), TEXT("UserWidget"), TEXT("AnimInstance"),
226
+ TEXT("GameInstance"), TEXT("SaveGame"), TEXT("DataAsset"), TEXT("PrimaryDataAsset"),
227
+ TEXT("BlueprintFunctionLibrary"), TEXT("DeveloperSettings"),
228
+ TEXT("CheatManager"), TEXT("WorldSubsystem"), TEXT("GameInstanceSubsystem"),
229
+ TEXT("LocalPlayerSubsystem"),
230
+ };
231
+
232
+ TArray<TSharedPtr<FJsonValue>> ClassesArray;
233
+ for (const FString& ClassName : CommonClasses)
234
+ {
235
+ UClass* Class = FindClass(ClassName);
236
+ if (Class)
237
+ {
238
+ TSharedPtr<FJsonObject> ClassObj = MakeShared<FJsonObject>();
239
+ ClassObj->SetStringField(TEXT("name"), Class->GetName());
240
+ if (Class->GetSuperClass())
241
+ {
242
+ ClassObj->SetStringField(TEXT("parent"), Class->GetSuperClass()->GetName());
243
+ }
244
+ ClassesArray.Add(MakeShared<FJsonValueObject>(ClassObj));
245
+ }
246
+ }
247
+ Result->SetStringField(TEXT("note"), TEXT("Showing common base classes. Use parentFilter to find derived classes."));
248
+ Result->SetArrayField(TEXT("classes"), ClassesArray);
249
+ Result->SetNumberField(TEXT("count"), ClassesArray.Num());
250
+ }
251
+
252
+ return MakeShared<FJsonValueObject>(Result);
253
+ }
254
+
255
+ TSharedPtr<FJsonValue> FReflectionHandlers::ListGameplayTags(const TSharedPtr<FJsonObject>& Params)
256
+ {
257
+ FString FilterPrefix;
258
+ Params->TryGetStringField(TEXT("filter"), FilterPrefix);
259
+
260
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
261
+
262
+ UGameplayTagsManager& TagsManager = UGameplayTagsManager::Get();
263
+ FGameplayTagContainer AllTags;
264
+ TagsManager.RequestAllGameplayTags(AllTags, false);
265
+
266
+ TArray<TSharedPtr<FJsonValue>> TagsArray;
267
+ for (const FGameplayTag& Tag : AllTags)
268
+ {
269
+ FString TagString = Tag.ToString();
270
+ if (FilterPrefix.IsEmpty() || TagString.StartsWith(FilterPrefix))
271
+ {
272
+ TagsArray.Add(MakeShared<FJsonValueString>(TagString));
273
+ }
274
+ }
275
+
276
+ TagsArray.Sort([](const TSharedPtr<FJsonValue>& A, const TSharedPtr<FJsonValue>& B) {
277
+ return A->AsString() < B->AsString();
278
+ });
279
+
280
+ Result->SetStringField(TEXT("filter"), FilterPrefix.IsEmpty() ? TEXT("(all)") : FilterPrefix);
281
+ Result->SetArrayField(TEXT("tags"), TagsArray);
282
+ Result->SetNumberField(TEXT("count"), TagsArray.Num());
283
+
284
+ return MakeShared<FJsonValueObject>(Result);
285
+ }
286
+
287
+ TSharedPtr<FJsonValue> FReflectionHandlers::CreateGameplayTag(const TSharedPtr<FJsonObject>& Params)
288
+ {
289
+ FString Tag;
290
+ if (!Params->TryGetStringField(TEXT("tag"), Tag) || Tag.IsEmpty())
291
+ {
292
+ TSharedPtr<FJsonObject> Error = MakeShared<FJsonObject>();
293
+ Error->SetStringField(TEXT("error"), TEXT("tag parameter is required (e.g. 'Combat.Damage.Fire')"));
294
+ return MakeShared<FJsonValueObject>(Error);
295
+ }
296
+
297
+ FString Comment;
298
+ Params->TryGetStringField(TEXT("comment"), Comment);
299
+
300
+ TSharedPtr<FJsonObject> Result = MakeShared<FJsonObject>();
301
+ Result->SetStringField(TEXT("tag"), Tag);
302
+
303
+ // Try to add via GameplayTagsManager
304
+ UGameplayTagsManager& TagsManager = UGameplayTagsManager::Get();
305
+ FName TagName(*Tag);
306
+ TagsManager.AddNativeGameplayTag(TagName, Comment);
307
+ FGameplayTag NewTag = TagsManager.RequestGameplayTag(TagName, false);
308
+ bool bSuccess = NewTag.IsValid();
309
+ if (bSuccess)
310
+ {
311
+ Result->SetBoolField(TEXT("success"), true);
312
+ Result->SetStringField(TEXT("method"), TEXT("add_native_gameplay_tag"));
313
+ return MakeShared<FJsonValueObject>(Result);
314
+ }
315
+
316
+ // Fallback: append to DefaultGameplayTags.ini
317
+ FString ProjectDir = FPaths::ProjectDir();
318
+ FString TagFile = FPaths::Combine(ProjectDir, TEXT("Config"), TEXT("DefaultGameplayTags.ini"));
319
+
320
+ FString Section = TEXT("[/Script/GameplayTags.GameplayTagsSettings]");
321
+ FString Entry = FString::Printf(TEXT("+GameplayTagList=(Tag=\"%s\",DevComment=\"%s\")"), *Tag, *Comment);
322
+
323
+ FString FileContent;
324
+ if (FFileHelper::LoadFileToString(FileContent, *TagFile))
325
+ {
326
+ if (!FileContent.Contains(Section))
327
+ {
328
+ FileContent += TEXT("\n\n") + Section + TEXT("\n") + Entry + TEXT("\n");
329
+ }
330
+ else if (!FileContent.Contains(Entry))
331
+ {
332
+ FileContent = FileContent.Replace(*Section, *(Section + TEXT("\n") + Entry));
333
+ }
334
+ }
335
+ else
336
+ {
337
+ FileContent = Section + TEXT("\n") + Entry + TEXT("\n");
338
+ }
339
+
340
+ if (FFileHelper::SaveStringToFile(FileContent, *TagFile))
341
+ {
342
+ Result->SetBoolField(TEXT("success"), true);
343
+ Result->SetStringField(TEXT("method"), TEXT("ini_append"));
344
+ Result->SetStringField(TEXT("note"), TEXT("Restart editor to pick up new tag"));
345
+ return MakeShared<FJsonValueObject>(Result);
346
+ }
347
+
348
+ Result->SetBoolField(TEXT("success"), false);
349
+ Result->SetStringField(TEXT("error"), TEXT("Could not add gameplay tag via available APIs"));
350
+ return MakeShared<FJsonValueObject>(Result);
351
+ }
352
+
353
+ UClass* FReflectionHandlers::FindClass(const FString& ClassName)
354
+ {
355
+ // Try direct lookup
356
+ UClass* Class = FindObject<UClass>(nullptr, *ClassName);
357
+ if (Class)
358
+ {
359
+ return Class;
360
+ }
361
+
362
+ // Try with /Script/ prefix
363
+ FString ScriptPath = FString::Printf(TEXT("/Script/%s"), *ClassName);
364
+ Class = FindObject<UClass>(nullptr, *ScriptPath);
365
+ if (Class)
366
+ {
367
+ return Class;
368
+ }
369
+
370
+ // Try with common prefixes
371
+ TArray<FString> Prefixes = { TEXT(""), TEXT("A"), TEXT("U"), TEXT("F") };
372
+ for (const FString& Prefix : Prefixes)
373
+ {
374
+ FString CandidateName = Prefix + ClassName;
375
+ Class = FindObject<UClass>(nullptr, *CandidateName);
376
+ if (Class)
377
+ {
378
+ return Class;
379
+ }
380
+
381
+ FString CandidatePath = FString::Printf(TEXT("/Script/%s"), *CandidateName);
382
+ Class = FindObject<UClass>(nullptr, *CandidatePath);
383
+ if (Class)
384
+ {
385
+ return Class;
386
+ }
387
+ }
388
+
389
+ return nullptr;
390
+ }
391
+
392
+ UScriptStruct* FReflectionHandlers::FindStruct(const FString& StructName)
393
+ {
394
+ // Try direct lookup (handles full paths like /Script/ModuleName.StructName)
395
+ UScriptStruct* Struct = FindObject<UScriptStruct>(nullptr, *StructName);
396
+ if (Struct)
397
+ {
398
+ return Struct;
399
+ }
400
+
401
+ // Try with /Script/ prefix
402
+ FString ScriptPath = FString::Printf(TEXT("/Script/%s"), *StructName);
403
+ Struct = FindObject<UScriptStruct>(nullptr, *ScriptPath);
404
+ if (Struct)
405
+ {
406
+ return Struct;
407
+ }
408
+
409
+ // Try with F prefix
410
+ FString FName = TEXT("F") + StructName;
411
+ Struct = FindObject<UScriptStruct>(nullptr, *FName);
412
+ if (Struct)
413
+ {
414
+ return Struct;
415
+ }
416
+
417
+ FString FPath = FString::Printf(TEXT("/Script/%s"), *FName);
418
+ Struct = FindObject<UScriptStruct>(nullptr, *FPath);
419
+ if (Struct)
420
+ {
421
+ return Struct;
422
+ }
423
+
424
+ // Iterate all loaded UScriptStruct objects to find by short name
425
+ // This catches project-defined structs in any module (e.g. /Script/MyModule.FMyStruct)
426
+ FString NameToFind = StructName;
427
+ FString FNameToFind = FName;
428
+ for (TObjectIterator<UScriptStruct> It; It; ++It)
429
+ {
430
+ UScriptStruct* Current = *It;
431
+ if (Current)
432
+ {
433
+ FString CurrentName = Current->GetName();
434
+ if (CurrentName == NameToFind || CurrentName == FNameToFind)
435
+ {
436
+ return Current;
437
+ }
438
+ }
439
+ }
440
+
441
+ return nullptr;
442
+ }
443
+
444
+ UEnum* FReflectionHandlers::FindEnum(const FString& EnumName)
445
+ {
446
+ // Try direct lookup
447
+ UEnum* Enum = FindObject<UEnum>(nullptr, *EnumName);
448
+ if (Enum)
449
+ {
450
+ return Enum;
451
+ }
452
+
453
+ // Try with /Script/ prefix
454
+ FString ScriptPath = FString::Printf(TEXT("/Script/%s"), *EnumName);
455
+ Enum = FindObject<UEnum>(nullptr, *ScriptPath);
456
+ if (Enum)
457
+ {
458
+ return Enum;
459
+ }
460
+
461
+ // Try with E prefix
462
+ FString EName = TEXT("E") + EnumName;
463
+ Enum = FindObject<UEnum>(nullptr, *EName);
464
+ if (Enum)
465
+ {
466
+ return Enum;
467
+ }
468
+
469
+ FString EPath = FString::Printf(TEXT("/Script/%s"), *EName);
470
+ Enum = FindObject<UEnum>(nullptr, *EPath);
471
+ if (Enum)
472
+ {
473
+ return Enum;
474
+ }
475
+
476
+ return nullptr;
477
+ }
478
+
479
+ TSharedPtr<FJsonValue> FReflectionHandlers::SerializeProperty(FProperty* Prop, void* Data)
480
+ {
481
+ // Basic property serialization - can be extended
482
+ if (CastField<FStrProperty>(Prop))
483
+ {
484
+ return MakeShared<FJsonValueString>(CastField<FStrProperty>(Prop)->GetPropertyValue(Data));
485
+ }
486
+ else if (CastField<FIntProperty>(Prop))
487
+ {
488
+ return MakeShared<FJsonValueNumber>(CastField<FIntProperty>(Prop)->GetPropertyValue(Data));
489
+ }
490
+ else if (CastField<FFloatProperty>(Prop))
491
+ {
492
+ return MakeShared<FJsonValueNumber>(CastField<FFloatProperty>(Prop)->GetPropertyValue(Data));
493
+ }
494
+ else if (CastField<FBoolProperty>(Prop))
495
+ {
496
+ return MakeShared<FJsonValueBoolean>(CastField<FBoolProperty>(Prop)->GetPropertyValue(Data));
497
+ }
498
+ return MakeShared<FJsonValueString>(TEXT("(unserializable)"));
499
+ }
@@ -0,0 +1,27 @@
1
+ #pragma once
2
+
3
+ #include "CoreMinimal.h"
4
+ #include "Dom/JsonValue.h"
5
+ #include "Dom/JsonObject.h"
6
+
7
+ class FReflectionHandlers
8
+ {
9
+ public:
10
+ // Register all reflection handlers
11
+ static void RegisterHandlers(class FMCPHandlerRegistry& Registry);
12
+
13
+ private:
14
+ // Handler implementations
15
+ static TSharedPtr<FJsonValue> ReflectClass(const TSharedPtr<FJsonObject>& Params);
16
+ static TSharedPtr<FJsonValue> ReflectStruct(const TSharedPtr<FJsonObject>& Params);
17
+ static TSharedPtr<FJsonValue> ReflectEnum(const TSharedPtr<FJsonObject>& Params);
18
+ static TSharedPtr<FJsonValue> ListClasses(const TSharedPtr<FJsonObject>& Params);
19
+ static TSharedPtr<FJsonValue> ListGameplayTags(const TSharedPtr<FJsonObject>& Params);
20
+ static TSharedPtr<FJsonValue> CreateGameplayTag(const TSharedPtr<FJsonObject>& Params);
21
+
22
+ // Helper functions
23
+ static UClass* FindClass(const FString& ClassName);
24
+ static UScriptStruct* FindStruct(const FString& StructName);
25
+ static UEnum* FindEnum(const FString& EnumName);
26
+ static TSharedPtr<FJsonValue> SerializeProperty(FProperty* Prop, void* Data);
27
+ };