Precompute broad type categories in WingTypes.
Move the broad-category classification logic out of TypeName_Search and into WingTypes, store the result in the type registry, and update TypeName_Search to print the cached category.
This commit is contained in:
@@ -1,13 +0,0 @@
|
|||||||
# Bugs in UE Wingman
|
|
||||||
|
|
||||||
- Partial TCP writes are not handled in [`Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp`](/home/jyelon/integration/Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp#L441). The server calls `Socket->Send(...)` once and ignores short writes, so large responses can be truncated and the client can block forever waiting for the terminating null byte.
|
|
||||||
|
|
||||||
- Unsigned numeric properties are validated incorrectly in [`Plugins/UEWingman/Source/UEWingman/Private/WingProperty.cpp`](/home/jyelon/integration/Plugins/UEWingman/Source/UEWingman/Private/WingProperty.cpp#L85) and [`Plugins/UEWingman/Source/UEWingman/Private/WingProperty.cpp`](/home/jyelon/integration/Plugins/UEWingman/Source/UEWingman/Private/WingProperty.cpp#L125). The code always reads back through `GetSignedIntPropertyValue`, which is the wrong check for unsigned properties and can reject valid values.
|
|
||||||
|
|
||||||
- UTF-8 decoding is done per recv chunk instead of on complete messages in [`Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp`](/home/jyelon/integration/Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp#L405). If a multibyte code point is split across TCP packets, the request can be corrupted before JSON parsing.
|
|
||||||
|
|
||||||
- Request execution is serialized to one queued message per editor tick in [`Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp`](/home/jyelon/integration/Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp#L227). Any slow handler blocks every connected client behind it because each client thread waits synchronously for its response.
|
|
||||||
|
|
||||||
- Shutdown can hang if a handler is already in flight in [`Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp`](/home/jyelon/integration/Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp#L188). Pending queued work is drained, but an active game-thread handler has no cancellation path, and client threads still wait on its unresolved promise.
|
|
||||||
|
|
||||||
- The shared output buffer is fixed at 65536 characters in [`Plugins/UEWingman/Source/UEWingman/Public/WingHandler.h`](/home/jyelon/integration/Plugins/UEWingman/Source/UEWingman/Public/WingHandler.h#L75) and instantiated in [`Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp`](/home/jyelon/integration/Plugins/UEWingman/Source/UEWingman/Private/WingServer.cpp#L502). Large dumps and manual output can be truncated with no warning.
|
|
||||||
|
|||||||
@@ -43,23 +43,6 @@ public:
|
|||||||
return Info.IsUserDefined && Info.PinSubCategoryObject.StartsWith(TEXT("/Game/"));
|
return Info.IsUserDefined && Info.PinSubCategoryObject.StartsWith(TEXT("/Game/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static FString BroadCategory(const UWingTypes::Info& Info)
|
|
||||||
{
|
|
||||||
if (Info.PinSubCategoryObject.IsEmpty()) return TEXT("Primitive");
|
|
||||||
if (Info.PinCategory == UEdGraphSchema_K2::PC_Enum) return TEXT("Enum");
|
|
||||||
if (Info.PinCategory == UEdGraphSchema_K2::PC_Struct) return TEXT("Struct");
|
|
||||||
if (Info.PinCategory == UEdGraphSchema_K2::PC_Interface) return TEXT("Interface");
|
|
||||||
if (Info.NativeParent)
|
|
||||||
{
|
|
||||||
if (Info.NativeParent->IsChildOf(UUserWidget::StaticClass())) return TEXT("Widget");
|
|
||||||
if (Info.NativeParent->IsChildOf(UActorComponent::StaticClass())) return TEXT("ActorComponent");
|
|
||||||
if (Info.NativeParent->IsChildOf(APawn::StaticClass())) return TEXT("Pawn");
|
|
||||||
if (Info.NativeParent->IsChildOf(AActor::StaticClass())) return TEXT("Actor");
|
|
||||||
if (Info.NativeParent->IsChildOf(UDataAsset::StaticClass())) return TEXT("DataAsset");
|
|
||||||
}
|
|
||||||
return TEXT("Object");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int Importance(const UWingTypes::Info& Info)
|
static int Importance(const UWingTypes::Info& Info)
|
||||||
{
|
{
|
||||||
if (IsProjectDefined(Info)) return 1;
|
if (IsProjectDefined(Info)) return 1;
|
||||||
@@ -94,9 +77,9 @@ public:
|
|||||||
{
|
{
|
||||||
const UWingTypes::Info& Info = *Matches[i];
|
const UWingTypes::Info& Info = *Matches[i];
|
||||||
if (IsProjectDefined(Info))
|
if (IsProjectDefined(Info))
|
||||||
WingOut::Stdout.Printf(TEXT("%s (%s, User-Defined)\n"), *Info.Short, *BroadCategory(Info));
|
WingOut::Stdout.Printf(TEXT("%s (%s, User-Defined)\n"), *Info.Short, *Info.BroadCategory.ToString());
|
||||||
else
|
else
|
||||||
WingOut::Stdout.Printf(TEXT("%s (%s)\n"), *Info.Short, *BroadCategory(Info));
|
WingOut::Stdout.Printf(TEXT("%s (%s)\n"), *Info.Short, *Info.BroadCategory.ToString());
|
||||||
}
|
}
|
||||||
if (Count >= Limit)
|
if (Count >= Limit)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,11 @@
|
|||||||
#include "AssetRegistry/AssetRegistryModule.h"
|
#include "AssetRegistry/AssetRegistryModule.h"
|
||||||
#include "Blueprint/BlueprintSupport.h"
|
#include "Blueprint/BlueprintSupport.h"
|
||||||
#include "Kismet2/KismetEditorUtilities.h"
|
#include "Kismet2/KismetEditorUtilities.h"
|
||||||
|
#include "GameFramework/Actor.h"
|
||||||
|
#include "Components/ActorComponent.h"
|
||||||
|
#include "Blueprint/UserWidget.h"
|
||||||
|
#include "GameFramework/Pawn.h"
|
||||||
|
#include "Engine/DataAsset.h"
|
||||||
|
|
||||||
|
|
||||||
static const FName NAME_TypeArray(TEXT("Array"));
|
static const FName NAME_TypeArray(TEXT("Array"));
|
||||||
@@ -137,6 +142,22 @@ const UClass *UWingTypes::FindNativeParent(const UClass *Obj)
|
|||||||
return Native;
|
return Native;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FName UWingTypes::BroadCategory(const UClass* Class)
|
||||||
|
{
|
||||||
|
// The nullptr case can really only happen if metadata is missing.
|
||||||
|
//
|
||||||
|
if (Class == nullptr) return("Unknown");
|
||||||
|
|
||||||
|
// Classify the object type.
|
||||||
|
//
|
||||||
|
if (Class->IsChildOf(UUserWidget::StaticClass())) return TEXT("Widget");
|
||||||
|
if (Class->IsChildOf(UActorComponent::StaticClass())) return TEXT("ActorComponent");
|
||||||
|
if (Class->IsChildOf(APawn::StaticClass())) return TEXT("Pawn");
|
||||||
|
if (Class->IsChildOf(AActor::StaticClass())) return TEXT("Actor");
|
||||||
|
if (Class->IsChildOf(UDataAsset::StaticClass())) return TEXT("DataAsset");
|
||||||
|
return TEXT("Object");
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Choose Short Name
|
// Choose Short Name
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -149,7 +170,7 @@ void UWingTypes::ReserveShortName(FName Name, FName PinCategory, FName PinSubCat
|
|||||||
Dummy.PinCategory = PinCategory;
|
Dummy.PinCategory = PinCategory;
|
||||||
Dummy.PinSubCategory = PinSubCategory;
|
Dummy.PinSubCategory = PinSubCategory;
|
||||||
Dummy.PinSubCategoryObject.Empty();
|
Dummy.PinSubCategoryObject.Empty();
|
||||||
Dummy.NativeParent = nullptr;
|
Dummy.BroadCategory = TEXT("Primitive");
|
||||||
Dummy.IsUserDefined = false;
|
Dummy.IsUserDefined = false;
|
||||||
ShortToInfo.Add(NameStr.ToLower(), MoveTemp(Dummy));
|
ShortToInfo.Add(NameStr.ToLower(), MoveTemp(Dummy));
|
||||||
}
|
}
|
||||||
@@ -166,7 +187,7 @@ FString UWingTypes::GetShortName(const FString &Path)
|
|||||||
return FString();
|
return FString();
|
||||||
}
|
}
|
||||||
|
|
||||||
FString UWingTypes::NewShortName(const FString &Path, FName PinCategory, const UClass *NativeParent, bool IsUserDefined)
|
FString UWingTypes::NewShortName(const FString &Path, FName PinCategory, FName BroadCategory, bool IsUserDefined)
|
||||||
{
|
{
|
||||||
// Verify that the path is not already associated.
|
// Verify that the path is not already associated.
|
||||||
check(!PathToShort.Find(Path));
|
check(!PathToShort.Find(Path));
|
||||||
@@ -187,7 +208,7 @@ FString UWingTypes::NewShortName(const FString &Path, FName PinCategory, const U
|
|||||||
Info TypeInfo;
|
Info TypeInfo;
|
||||||
TypeInfo.PinCategory = PinCategory;
|
TypeInfo.PinCategory = PinCategory;
|
||||||
TypeInfo.PinSubCategoryObject = Path;
|
TypeInfo.PinSubCategoryObject = Path;
|
||||||
TypeInfo.NativeParent = NativeParent;
|
TypeInfo.BroadCategory = BroadCategory;
|
||||||
TypeInfo.IsUserDefined = IsUserDefined;
|
TypeInfo.IsUserDefined = IsUserDefined;
|
||||||
|
|
||||||
// Check if the proposed name is available.
|
// Check if the proposed name is available.
|
||||||
@@ -231,12 +252,14 @@ FString UWingTypes::ChooseShortName(const UObject* Obj)
|
|||||||
|
|
||||||
if (Cast<UEnum>(Obj))
|
if (Cast<UEnum>(Obj))
|
||||||
{
|
{
|
||||||
return NewShortName(Path, UEdGraphSchema_K2::PC_Enum, nullptr, Cast<UUserDefinedEnum>(Obj) != nullptr);
|
return NewShortName(Path, UEdGraphSchema_K2::PC_Enum, TEXT("Enum"),
|
||||||
|
Cast<UUserDefinedEnum>(Obj) != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Cast<UScriptStruct>(Obj))
|
if (Cast<UScriptStruct>(Obj))
|
||||||
{
|
{
|
||||||
return NewShortName(Path, UEdGraphSchema_K2::PC_Struct, nullptr, Cast<UUserDefinedStruct>(Obj) != nullptr);
|
return NewShortName(Path, UEdGraphSchema_K2::PC_Struct, TEXT("Struct"),
|
||||||
|
Cast<UUserDefinedStruct>(Obj) != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const UClass* Class = Cast<UClass>(Obj))
|
if (const UClass* Class = Cast<UClass>(Obj))
|
||||||
@@ -244,7 +267,7 @@ FString UWingTypes::ChooseShortName(const UObject* Obj)
|
|||||||
bool IsInterface = Class->IsChildOf(UInterface::StaticClass());
|
bool IsInterface = Class->IsChildOf(UInterface::StaticClass());
|
||||||
bool IsUserDefined = (Class->ClassGeneratedBy != nullptr);
|
bool IsUserDefined = (Class->ClassGeneratedBy != nullptr);
|
||||||
FName PinCategory = IsInterface ? UEdGraphSchema_K2::PC_Interface : UEdGraphSchema_K2::PC_Object;
|
FName PinCategory = IsInterface ? UEdGraphSchema_K2::PC_Interface : UEdGraphSchema_K2::PC_Object;
|
||||||
return NewShortName(Path, PinCategory, FindNativeParent(Class), IsUserDefined);
|
return NewShortName(Path, PinCategory, BroadCategory(Class), IsUserDefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FString();
|
return FString();
|
||||||
@@ -261,7 +284,7 @@ void UWingTypes::ChooseShortName(const FAssetData &Data)
|
|||||||
{
|
{
|
||||||
FString Path = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName);
|
FString Path = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName);
|
||||||
if (!GetShortName(Path).IsEmpty()) return;
|
if (!GetShortName(Path).IsEmpty()) return;
|
||||||
NewShortName(Path, UEdGraphSchema_K2::PC_Struct, nullptr, true);
|
NewShortName(Path, UEdGraphSchema_K2::PC_Struct, TEXT("Struct"), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +293,7 @@ void UWingTypes::ChooseShortName(const FAssetData &Data)
|
|||||||
{
|
{
|
||||||
FString Path = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName);
|
FString Path = FString::Printf(TEXT("%s.%s"), *PackageName, *AssetName);
|
||||||
if (!GetShortName(Path).IsEmpty()) return;
|
if (!GetShortName(Path).IsEmpty()) return;
|
||||||
NewShortName(Path, UEdGraphSchema_K2::PC_Enum, nullptr, true);
|
NewShortName(Path, UEdGraphSchema_K2::PC_Enum, TEXT("Enum"), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,12 +317,12 @@ void UWingTypes::ChooseShortName(const FAssetData &Data)
|
|||||||
if (BPType == TEXT("BPTYPE_Interface"))
|
if (BPType == TEXT("BPTYPE_Interface"))
|
||||||
{
|
{
|
||||||
check(NativeParent->IsChildOf(UInterface::StaticClass()));
|
check(NativeParent->IsChildOf(UInterface::StaticClass()));
|
||||||
NewShortName(Path, UEdGraphSchema_K2::PC_Interface, NativeParent, true);
|
NewShortName(Path, UEdGraphSchema_K2::PC_Interface, TEXT("Interface"), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (BPType == TEXT("BPTYPE_Normal") || BPType == TEXT("BPTYPE_Const"))
|
else if (BPType == TEXT("BPTYPE_Normal") || BPType == TEXT("BPTYPE_Const"))
|
||||||
{
|
{
|
||||||
NewShortName(Path, UEdGraphSchema_K2::PC_Object, NativeParent, true);
|
NewShortName(Path, UEdGraphSchema_K2::PC_Object, BroadCategory(NativeParent), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -776,4 +799,3 @@ void UWingTypes::Deinitialize()
|
|||||||
}
|
}
|
||||||
Super::Deinitialize();
|
Super::Deinitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public:
|
|||||||
FName PinSubCategory;
|
FName PinSubCategory;
|
||||||
FString PinSubCategoryObject;
|
FString PinSubCategoryObject;
|
||||||
// The following are only set for interfaces and Objects.
|
// The following are only set for interfaces and Objects.
|
||||||
const UClass *NativeParent = nullptr;
|
FName BroadCategory;
|
||||||
bool IsUserDefined = false;
|
bool IsUserDefined = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,6 +68,8 @@ private:
|
|||||||
// Choose Short Name
|
// Choose Short Name
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static FName BroadCategory(const UClass* Class);
|
||||||
|
|
||||||
// Reserve the short name for a primitive type.
|
// Reserve the short name for a primitive type.
|
||||||
void ReserveShortName(FName Name, FName PinCategory, FName PinSubCategory);
|
void ReserveShortName(FName Name, FName PinCategory, FName PinSubCategory);
|
||||||
void ReserveShortName(FName Name);
|
void ReserveShortName(FName Name);
|
||||||
@@ -77,7 +79,7 @@ private:
|
|||||||
|
|
||||||
// Core version: choose a short name for a path that doesn't already
|
// Core version: choose a short name for a path that doesn't already
|
||||||
// have a short name. Records all the associated information.
|
// have a short name. Records all the associated information.
|
||||||
FString NewShortName(const FString &Path, FName PinCategory, const UClass *NativeParent, bool IsUserDefined);
|
FString NewShortName(const FString &Path, FName PinCategory, FName BroadCategory, bool IsUserDefined);
|
||||||
|
|
||||||
// Choose a short name for an already-loaded UObject.
|
// Choose a short name for an already-loaded UObject.
|
||||||
FString ChooseShortName(const UObject* Obj);
|
FString ChooseShortName(const UObject* Obj);
|
||||||
|
|||||||
Reference in New Issue
Block a user