diff --git a/Config/BaseVaRest.ini b/Config/BaseVaRest.ini index 22766973..0ad8fd95 100644 --- a/Config/BaseVaRest.ini +++ b/Config/BaseVaRest.ini @@ -6,9 +6,19 @@ +ClassRedirects=(OldName="/Script/VaRestPlugin.VaRestRequestJSON",NewName="/Script/VaRest.VaRestRequestJSON") +StructRedirects=(OldName="/Script/VaRestPlugin.VaRestCallResponse",NewName="/Script/VaRest.VaRestCallResponse") +EnumRedirects=(OldName="/Script/VaRestPlugin.EVaJson",NewName="/Script/VaRest.EVaJson") -+EnumRedirects=(OldName="/Script/VaRestPlugin.ERequestVerb",NewName="/Script/VaRest.ERequestVerb") -+EnumRedirects=(OldName="/Script/VaRestPlugin.ERequestContentType",NewName="/Script/VaRest.ERequestContentType") -+EnumRedirects=(OldName="/Script/VaRestPlugin.ERequestStatus",NewName="/Script/VaRest.ERequestStatus") ++EnumRedirects=(OldName="/Script/VaRestPlugin.EVaRestRequestVerb",NewName="/Script/VaRest.EVaRestRequestVerb") ++EnumRedirects=(OldName="/Script/VaRestPlugin.EVaRestRequestContentType",NewName="/Script/VaRest.EVaRestRequestContentType") ++EnumRedirects=(OldName="/Script/VaRestPlugin.EVaRestRequestStatus",NewName="/Script/VaRest.EVaRestRequestStatus") ++EnumRedirects=(OldName="/Script/VaRest.ERequestVerb",NewName="/Script/VaRest.EVaRestRequestVerb") ++EnumRedirects=(OldName="/Script/VaRest.ERequestContentType",NewName="/Script/VaRest.EVaRestRequestContentType") ++EnumRedirects=(OldName="/Script/VaRest.ERequestStatus",NewName="/Script/VaRest.EVaRestRequestStatus") ++EnumRedirects=(OldName="/Script/VaRest.EHttpStatusCode",NewName="/Script/VaRest.EVaRestHttpStatusCode") +FunctionRedirects=(OldName="VaRestRequestJSON.ConstructRequest",NewName="VaRestRequestJSON.ConstructVaRestRequest") +FunctionRedirects=(OldName="VaRestRequestJSON.ConstructRequestExt",NewName="VaRestRequestJSON.ConstructVaRestRequestExt") +FunctionRedirects=(OldName="VaRestJsonObject.ConstructJsonObject",NewName="VaRestJsonObject.ConstructVaRestJsonObject") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueNumber",NewName="VaRestSubsystem.ConstructJsonValueNumber") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueString",NewName="VaRestSubsystem.ConstructJsonValueString") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueBool",NewName="VaRestSubsystem.ConstructJsonValueBool") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueArray",NewName="VaRestSubsystem.ConstructJsonValueArray") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueObject",NewName="VaRestSubsystem.ConstructJsonValueObject") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValue",NewName="VaRestSubsystem.ConstructJsonValue") \ No newline at end of file diff --git a/Config/DefaultVaRest.ini b/Config/DefaultVaRest.ini index 22766973..0ad8fd95 100644 --- a/Config/DefaultVaRest.ini +++ b/Config/DefaultVaRest.ini @@ -6,9 +6,19 @@ +ClassRedirects=(OldName="/Script/VaRestPlugin.VaRestRequestJSON",NewName="/Script/VaRest.VaRestRequestJSON") +StructRedirects=(OldName="/Script/VaRestPlugin.VaRestCallResponse",NewName="/Script/VaRest.VaRestCallResponse") +EnumRedirects=(OldName="/Script/VaRestPlugin.EVaJson",NewName="/Script/VaRest.EVaJson") -+EnumRedirects=(OldName="/Script/VaRestPlugin.ERequestVerb",NewName="/Script/VaRest.ERequestVerb") -+EnumRedirects=(OldName="/Script/VaRestPlugin.ERequestContentType",NewName="/Script/VaRest.ERequestContentType") -+EnumRedirects=(OldName="/Script/VaRestPlugin.ERequestStatus",NewName="/Script/VaRest.ERequestStatus") ++EnumRedirects=(OldName="/Script/VaRestPlugin.EVaRestRequestVerb",NewName="/Script/VaRest.EVaRestRequestVerb") ++EnumRedirects=(OldName="/Script/VaRestPlugin.EVaRestRequestContentType",NewName="/Script/VaRest.EVaRestRequestContentType") ++EnumRedirects=(OldName="/Script/VaRestPlugin.EVaRestRequestStatus",NewName="/Script/VaRest.EVaRestRequestStatus") ++EnumRedirects=(OldName="/Script/VaRest.ERequestVerb",NewName="/Script/VaRest.EVaRestRequestVerb") ++EnumRedirects=(OldName="/Script/VaRest.ERequestContentType",NewName="/Script/VaRest.EVaRestRequestContentType") ++EnumRedirects=(OldName="/Script/VaRest.ERequestStatus",NewName="/Script/VaRest.EVaRestRequestStatus") ++EnumRedirects=(OldName="/Script/VaRest.EHttpStatusCode",NewName="/Script/VaRest.EVaRestHttpStatusCode") +FunctionRedirects=(OldName="VaRestRequestJSON.ConstructRequest",NewName="VaRestRequestJSON.ConstructVaRestRequest") +FunctionRedirects=(OldName="VaRestRequestJSON.ConstructRequestExt",NewName="VaRestRequestJSON.ConstructVaRestRequestExt") +FunctionRedirects=(OldName="VaRestJsonObject.ConstructJsonObject",NewName="VaRestJsonObject.ConstructVaRestJsonObject") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueNumber",NewName="VaRestSubsystem.ConstructJsonValueNumber") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueString",NewName="VaRestSubsystem.ConstructJsonValueString") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueBool",NewName="VaRestSubsystem.ConstructJsonValueBool") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueArray",NewName="VaRestSubsystem.ConstructJsonValueArray") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValueObject",NewName="VaRestSubsystem.ConstructJsonValueObject") ++FunctionRedirects=(OldName="VaRestJsonValue.ConstructJsonValue",NewName="VaRestSubsystem.ConstructJsonValue") \ No newline at end of file diff --git a/README.md b/README.md index b13aa22d..e9ee079f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![statusIcon](https://teamcity.ufna.dev/app/rest/builds/buildType:(id:UfnaDev_VaRest_ClangFormatCheck)/statusIcon.svg)](https://teamcity.ufna.dev/viewType.html?buildTypeId=UfnaDev_VaRest_ClangFormatCheck&guest=1) +[![statusIcon](https://teamcity.ufna.dev/app/rest/builds/buildType:(id:UfnaDev_VaRest_BuildPlugin)/statusIcon.svg)](https://teamcity.ufna.dev/viewType.html?buildTypeId=UfnaDev_VaRest_BuildPlugin&guest=1) ![GitHub](https://img.shields.io/github/license/ufna/VaRest) ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/ufna/VaRest?include_prereleases) @@ -16,7 +16,7 @@ Key features: Check the [Wiki](http://bit.ly/VaRest-Docs) for plugin usage examples and installation notes. -Current version: **1.1 R 26** (UE 4.19-4.23) +Current version: **1.1.33** (UE 4.27; please check the [5.0](https://github.com/ufna/VaRest/tree/5.0) branch for UE5 EA support). ![SCREENSHOT](SCREENSHOT.jpg) @@ -26,5 +26,5 @@ Legal info Unreal® is a trademark or registered trademark of Epic Games, Inc. in the United States of America and elsewhere. -Unreal® Engine, Copyright 1998 – 2018, Epic Games, Inc. All rights reserved. +Unreal® Engine, Copyright 1998 – 2021, Epic Games, Inc. All rights reserved. diff --git a/Source/VaRest/Private/VaRest.cpp b/Source/VaRest/Private/VaRest.cpp index 45944a2f..f4829540 100644 --- a/Source/VaRest/Private/VaRest.cpp +++ b/Source/VaRest/Private/VaRest.cpp @@ -3,7 +3,56 @@ #include "VaRest.h" #include "VaRestDefines.h" +#include "VaRestLibrary.h" +#include "VaRestSettings.h" + +#include "Developer/Settings/Public/ISettingsModule.h" +#include "UObject/Package.h" + +#define LOCTEXT_NAMESPACE "FVaRestModule" + +void FVaRestModule::StartupModule() +{ + ModuleSettings = NewObject(GetTransientPackage(), "VaRestSettings", RF_Standalone); + ModuleSettings->AddToRoot(); + + // Register settings + if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings")) + { + SettingsModule->RegisterSettings("Project", "Plugins", "VaRest", + LOCTEXT("RuntimeSettingsName", "VaRest"), + LOCTEXT("RuntimeSettingsDescription", "Configure VaRest plugin settings"), + ModuleSettings); + } + + UE_LOG(LogVaRest, Log, TEXT("%s: VaRest (%s) module started"), *VA_FUNC_LINE, *UVaRestLibrary::GetVaRestVersion()); +} + +void FVaRestModule::ShutdownModule() +{ + if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings")) + { + SettingsModule->UnregisterSettings("Project", "Plugins", "VaRest"); + } + + if (!GExitPurge) + { + ModuleSettings->RemoveFromRoot(); + } + else + { + ModuleSettings = nullptr; + } +} + +UVaRestSettings* FVaRestModule::GetSettings() const +{ + check(ModuleSettings); + return ModuleSettings; +} IMPLEMENT_MODULE(FVaRestModule, VaRest) DEFINE_LOG_CATEGORY(LogVaRest); + +#undef LOCTEXT_NAMESPACE diff --git a/Source/VaRest/Private/VaRestJsonObject.cpp b/Source/VaRest/Private/VaRestJsonObject.cpp index 93081d8d..7c3a9666 100644 --- a/Source/VaRest/Private/VaRestJsonObject.cpp +++ b/Source/VaRest/Private/VaRestJsonObject.cpp @@ -46,7 +46,7 @@ void UVaRestJsonObject::SetRootObject(const TSharedPtr& JsonObject) FString UVaRestJsonObject::EncodeJson() const { FString OutputString; - TSharedRef Writer = FCondensedJsonStringWriterFactory::Create(&OutputString); + const auto Writer = TJsonWriterFactory<>::Create(&OutputString); FJsonSerializer::Serialize(JsonObj, Writer); return OutputString; @@ -54,13 +54,9 @@ FString UVaRestJsonObject::EncodeJson() const FString UVaRestJsonObject::EncodeJsonToSingleString() const { - FString OutputString = EncodeJson(); - - // Remove line terminators - OutputString.Replace(LINE_TERMINATOR, TEXT("")); - - // Remove tabs - OutputString.Replace(LINE_TERMINATOR, TEXT("\t")); + FString OutputString; + const auto Writer = FCondensedJsonStringWriterFactory::Create(&OutputString); + FJsonSerializer::Serialize(JsonObj, Writer); return OutputString; } @@ -69,7 +65,7 @@ bool UVaRestJsonObject::DecodeJson(const FString& JsonString, bool bUseIncrement { if (bUseIncrementalParser) { - int32 BytesRead = DeserializeFromTCHARBytes(JsonString.GetCharArray().GetData(), JsonString.Len()); + const int32 BytesRead = DeserializeFromTCHARBytes(JsonString.GetCharArray().GetData(), JsonString.Len()); // JsonObj is always valid, but read bytes is zero when something went wrong if (BytesRead > 0) @@ -79,7 +75,7 @@ bool UVaRestJsonObject::DecodeJson(const FString& JsonString, bool bUseIncrement } else { - TSharedRef> Reader = TJsonReaderFactory<>::Create(*JsonString); + const TSharedRef> Reader = TJsonReaderFactory<>::Create(*JsonString); TSharedPtr OutJsonObj; if (FJsonSerializer::Deserialize(Reader, OutJsonObj)) { @@ -201,6 +197,27 @@ void UVaRestJsonObject::SetIntegerField(const FString& FieldName, int32 Number) JsonObj->SetNumberField(FieldName, Number); } +int64 UVaRestJsonObject::GetInt64Field(const FString& FieldName) const +{ + if (!JsonObj->HasTypedField(FieldName)) + { + UE_LOG(LogVaRest, Warning, TEXT("No field with name %s of type Number"), *FieldName); + return 0; + } + + return static_cast(JsonObj->GetNumberField(FieldName)); +} + +void UVaRestJsonObject::SetInt64Field(const FString& FieldName, int64 Number) +{ + if (FieldName.IsEmpty()) + { + return; + } + + JsonObj->SetNumberField(FieldName, Number); +} + FString UVaRestJsonObject::GetStringField(const FString& FieldName) const { if (!JsonObj->HasTypedField(FieldName)) @@ -281,7 +298,7 @@ void UVaRestJsonObject::SetArrayField(const FString& FieldName, const TArray JsonVal = InVal->GetRootValue(); + const TSharedPtr JsonVal = InVal->GetRootValue(); switch (InVal->GetType()) { @@ -348,7 +365,7 @@ UVaRestJsonObject* UVaRestJsonObject::GetObjectField(const FString& FieldName) c return nullptr; } - TSharedPtr JsonObjField = JsonObj->GetObjectField(FieldName); + const TSharedPtr JsonObjField = JsonObj->GetObjectField(FieldName); UVaRestJsonObject* OutRestJsonObj = NewObject(); OutRestJsonObj->SetRootObject(JsonObjField); @@ -366,31 +383,45 @@ void UVaRestJsonObject::SetObjectField(const FString& FieldName, UVaRestJsonObje JsonObj->SetObjectField(FieldName, JsonObject->GetRootObject()); } -////////////////////////////////////////////////////////////////////////// -// Array fields helpers (uniform arrays) - -TArray UVaRestJsonObject::GetNumberArrayField(const FString& FieldName) const +void UVaRestJsonObject::SetMapFields_string(const TMap& Fields) { - TArray NumberArray; - if (!JsonObj->HasTypedField(FieldName) || FieldName.IsEmpty()) + for (auto& field : Fields) { - UE_LOG(LogVaRest, Warning, TEXT("%s: No field with name %s of type Array"), *VA_FUNC_LINE, *FieldName); - return NumberArray; + SetStringField(field.Key, field.Value); } +} - TArray> JsonArrayValues = JsonObj->GetArrayField(FieldName); - for (TArray>::TConstIterator It(JsonArrayValues); It; ++It) - { - auto Value = (*It).Get(); - if (Value->Type != EJson::Number) - { - UE_LOG(LogVaRest, Error, TEXT("Not Number element in array with field name %s"), *FieldName); - } +void UVaRestJsonObject::SetMapFields_uint8(const TMap& Fields) +{ + SetMapFields_Impl(Fields); +} - NumberArray.Add((*It)->AsNumber()); - } +void UVaRestJsonObject::SetMapFields_int32(const TMap& Fields) +{ + SetMapFields_Impl(Fields); +} + +void UVaRestJsonObject::SetMapFields_int64(const TMap& Fields) +{ + SetMapFields_Impl(Fields); +} - return NumberArray; +void UVaRestJsonObject::SetMapFields_bool(const TMap& Fields) +{ + SetMapFields_Impl(Fields); +} + +////////////////////////////////////////////////////////////////////////// +// Array fields helpers (uniform arrays) + +TArray UVaRestJsonObject::GetNumberArrayField(const FString& FieldName) const +{ + return GetTypeArrayField(FieldName); +} + +TArray UVaRestJsonObject::GetIntegerArrayField(const FString& FieldName) const +{ + return GetTypeArrayField(FieldName); } void UVaRestJsonObject::SetNumberArrayField(const FString& FieldName, const TArray& NumberArray) @@ -419,10 +450,10 @@ TArray UVaRestJsonObject::GetStringArrayField(const FString& FieldName) return StringArray; } - TArray> JsonArrayValues = JsonObj->GetArrayField(FieldName); + const TArray> JsonArrayValues = JsonObj->GetArrayField(FieldName); for (TArray>::TConstIterator It(JsonArrayValues); It; ++It) { - auto Value = (*It).Get(); + const auto Value = (*It).Get(); if (Value->Type != EJson::String) { UE_LOG(LogVaRest, Error, TEXT("Not String element in array with field name %s"), *FieldName); @@ -459,10 +490,10 @@ TArray UVaRestJsonObject::GetBoolArrayField(const FString& FieldName) cons return BoolArray; } - TArray> JsonArrayValues = JsonObj->GetArrayField(FieldName); + const TArray> JsonArrayValues = JsonObj->GetArrayField(FieldName); for (TArray>::TConstIterator It(JsonArrayValues); It; ++It) { - auto Value = (*It).Get(); + const auto Value = (*It).Get(); if (Value->Type != EJson::Boolean) { UE_LOG(LogVaRest, Error, TEXT("Not Boolean element in array with field name %s"), *FieldName); @@ -500,7 +531,7 @@ TArray UVaRestJsonObject::GetObjectArrayField(const FString& } TArray> ValArray = JsonObj->GetArrayField(FieldName); - for (auto Value : ValArray) + for (const auto& Value : ValArray) { if (Value->Type != EJson::Object) { @@ -544,11 +575,7 @@ int32 UVaRestJsonObject::DeserializeFromUTF8Bytes(const ANSICHAR* Bytes, int32 S const ANSICHAR* EndByte = Bytes + Size; while (Bytes < EndByte) { -#if ENGINE_MINOR_VERSION >= 19 TCHAR Char = FUtf8Helper::CodepointFromUtf8(Bytes, EndByte - Bytes); -#else - TCHAR Char = FUTF8ToTCHAR_Convert::utf8codepoint(&Bytes); -#endif if (Char > 0xFFFF) { Char = UNICODE_BOGUS_CHAR_CODEPOINT; @@ -619,11 +646,11 @@ void UVaRestJsonObject::DecodeFromArchive(TUniquePtr& Reader) if (bIsIntelByteOrder) { - Char = CharCast((UCS2CHAR)((uint16)SymbolBytes[0] + (uint16)SymbolBytes[1] * 256)); + Char = CharCast(static_cast(static_cast(SymbolBytes[0]) + static_cast(SymbolBytes[1]) * 256)); } else { - Char = CharCast((UCS2CHAR)((uint16)SymbolBytes[1] + (uint16)SymbolBytes[0] * 256)); + Char = CharCast(static_cast(static_cast(SymbolBytes[1]) + static_cast(SymbolBytes[0]) * 256)); } if (!JsonReader.Read(Char)) @@ -643,7 +670,7 @@ void UVaRestJsonObject::DecodeFromArchive(TUniquePtr& Reader) ////////////////////////////////////////////////////////////////////////// // Serialize -bool UVaRestJsonObject::WriteToFile(const FString& Path) +bool UVaRestJsonObject::WriteToFile(const FString& Path) const { TUniquePtr FileWriter(IFileManager::Get().CreateFileWriter(*Path)); if (!FileWriter) @@ -699,8 +726,8 @@ bool UVaRestJsonObject::WriteToFilePath(const FString& Path, const bool bIsRelat bool UVaRestJsonObject::WriteStringToArchive(FArchive& Ar, const TCHAR* StrPtr, int64 Len) { - auto Src = StringCast(StrPtr, Len); - Ar.Serialize((UCS2CHAR*)Src.Get(), Src.Length() * sizeof(UCS2CHAR)); + const auto Src = StringCast(StrPtr, Len); + Ar.Serialize(const_cast(Src.Get()), Src.Length() * sizeof(UCS2CHAR)); return true; } diff --git a/Source/VaRest/Private/VaRestJsonParser.cpp b/Source/VaRest/Private/VaRestJsonParser.cpp index ee629434..5a7a6ded 100644 --- a/Source/VaRest/Private/VaRestJsonParser.cpp +++ b/Source/VaRest/Private/VaRestJsonParser.cpp @@ -6,7 +6,6 @@ #include "Dom/JsonObject.h" #include "Dom/JsonValue.h" -#include "Logging/LogMacros.h" uint32 FUtf8Helper::CodepointFromUtf8(const ANSICHAR*& SourceString, const uint32 SourceLengthRemaining) { @@ -294,7 +293,7 @@ void FJSONState::PopObject() { if (Objects.Num() > 0) { - auto Object = Objects.Pop(false); + const auto Object = Objects.Pop(false); if (Object->Type == EJson::Object) { return; @@ -308,7 +307,7 @@ void FJSONState::PopArray() { if (Objects.Num() > 0) { - auto Object = Objects.Pop(false); + const auto Object = Objects.Pop(false); if (Object->Type == EJson::Array) { return; @@ -322,7 +321,7 @@ void FJSONState::PopValue(bool bCheckType) { if (Objects.Num() > 0) { - auto Value = Objects.Last(0); + const auto Value = Objects.Last(0); if (Value->Type == EJson::Object || Value->Type == EJson::Array) { if (bCheckType) @@ -339,7 +338,7 @@ void FJSONState::PopValue(bool bCheckType) { case EJson::Null: { - auto LowerCase = Data.ToLower(); + const auto LowerCase = Data.ToLower(); if (LowerCase != TEXT("null")) { bError = true; @@ -356,7 +355,7 @@ void FJSONState::PopValue(bool bCheckType) } case EJson::Number: { - FString LowerCase = Data.ToLower(); + const FString LowerCase = Data.ToLower(); int32 ePosition = INDEX_NONE; LowerCase.FindChar('e', ePosition); if (ePosition == INDEX_NONE) @@ -372,8 +371,8 @@ void FJSONState::PopValue(bool bCheckType) } else if (LowerCase.Len() > ePosition + 2) { - FString Left = LowerCase.Left(ePosition); - FString Rigth = LowerCase.Right(LowerCase.Len() - ePosition - 1); + const FString Left = LowerCase.Left(ePosition); + const FString Rigth = LowerCase.Right(LowerCase.Len() - ePosition - 1); if (Left.IsNumeric() && Rigth.IsNumeric()) { ((FJsonValueNonConstNumber*)Value.Get())->AsNonConstNumber() = FCString::Atod(*Left) * FMath::Pow(10.f, FCString::Atoi(*Rigth)); @@ -391,7 +390,7 @@ void FJSONState::PopValue(bool bCheckType) } case EJson::Boolean: { - auto LowerCase = Data.ToLower(); + const auto LowerCase = Data.ToLower(); if (LowerCase == TEXT("true")) { ((FJsonValueNonConstBoolean*)Value.Get())->AsNonConstBool() = true; @@ -415,7 +414,7 @@ void FJSONState::PopValue(bool bCheckType) ClearData(); - auto Container = Objects.Last(0); + const auto Container = Objects.Last(0); if (Container->Type == EJson::Object) { if (Key.Len() > 0) @@ -502,7 +501,7 @@ TSharedPtr FJSONState::PushObject(TSharedPtr Obje TSharedPtr FJSONState::PushArray() { - TArray> Empty; + const TArray> Empty; TSharedPtr Result(new FJsonValueNonConstArray(Empty)); Objects.Add(Result); Size += sizeof(TSharedPtr) + sizeof(FJsonValueNonConstArray); @@ -627,7 +626,7 @@ void FJSONReader::UpdateNotation() if (State.Key.Len() > 0) { State.Notation = EJSONNotation::OBJECT; - auto Value = State.GetObject(); + const auto Value = State.GetObject(); if (Value != nullptr) { Value->AsObject()->SetField(State.Key, State.PushObject()); @@ -709,7 +708,7 @@ void FJSONReader::UpdateNotation() State.Notation = EJSONNotation::ARRAY; if (State.Key.Len() > 0) { - auto Value = State.GetObject(); + const auto Value = State.GetObject(); if (Value != nullptr) { Value->AsObject()->SetField(State.Key, State.PushArray()); @@ -1100,7 +1099,7 @@ void FJSONWriter::Write(TSharedPtr JsonValue, FArchive* Writer, bool } default: { - FString Value = JsonValue->AsString(); + const FString Value = JsonValue->AsString(); const TCHAR* BufferPtr = *Value; for (int i = 0; i < Value.Len(); ++i) diff --git a/Source/VaRest/Private/VaRestJsonValue.cpp b/Source/VaRest/Private/VaRestJsonValue.cpp index 3895ae09..043d2d99 100644 --- a/Source/VaRest/Private/VaRestJsonValue.cpp +++ b/Source/VaRest/Private/VaRestJsonValue.cpp @@ -10,71 +10,9 @@ UVaRestJsonValue::UVaRestJsonValue(const FObjectInitializer& ObjectInitializer) { } -UVaRestJsonValue* UVaRestJsonValue::ConstructJsonValueNumber(UObject* WorldContextObject, float Number) +void UVaRestJsonValue::Reset() { - TSharedPtr NewVal = MakeShareable(new FJsonValueNumber(Number)); - - UVaRestJsonValue* NewValue = NewObject(); - NewValue->SetRootValue(NewVal); - - return NewValue; -} - -UVaRestJsonValue* UVaRestJsonValue::ConstructJsonValueString(UObject* WorldContextObject, const FString& StringValue) -{ - TSharedPtr NewVal = MakeShareable(new FJsonValueString(StringValue)); - - UVaRestJsonValue* NewValue = NewObject(); - NewValue->SetRootValue(NewVal); - - return NewValue; -} - -UVaRestJsonValue* UVaRestJsonValue::ConstructJsonValueBool(UObject* WorldContextObject, bool InValue) -{ - TSharedPtr NewVal = MakeShareable(new FJsonValueBoolean(InValue)); - - UVaRestJsonValue* NewValue = NewObject(); - NewValue->SetRootValue(NewVal); - - return NewValue; -} - -UVaRestJsonValue* UVaRestJsonValue::ConstructJsonValueArray(UObject* WorldContextObject, const TArray& InArray) -{ - // Prepare data array to create new value - TArray> ValueArray; - for (auto InVal : InArray) - { - ValueArray.Add(InVal->GetRootValue()); - } - - TSharedPtr NewVal = MakeShareable(new FJsonValueArray(ValueArray)); - - UVaRestJsonValue* NewValue = NewObject(); - NewValue->SetRootValue(NewVal); - - return NewValue; -} - -UVaRestJsonValue* UVaRestJsonValue::ConstructJsonValueObject(UObject* WorldContextObject, UVaRestJsonObject* JsonObject) -{ - TSharedPtr NewVal = MakeShareable(new FJsonValueObject(JsonObject->GetRootObject())); - - UVaRestJsonValue* NewValue = NewObject(); - NewValue->SetRootValue(NewVal); - - return NewValue; -} - -UVaRestJsonValue* ConstructJsonValue(UObject* WorldContextObject, const TSharedPtr& InValue) -{ - TSharedPtr NewVal = InValue; - - UVaRestJsonValue* NewValue = NewObject(); - NewValue->SetRootValue(NewVal); - - return NewValue; + JsonVal = nullptr; } TSharedPtr& UVaRestJsonValue::GetRootValue() @@ -178,7 +116,29 @@ float UVaRestJsonValue::AsNumber() const return 0.f; } - return JsonVal->AsNumber(); + return static_cast(JsonVal->AsNumber()); +} + +int32 UVaRestJsonValue::AsInt32() const +{ + if (!JsonVal.IsValid()) + { + ErrorMessage(TEXT("Number")); + return 0.f; + } + + return static_cast(JsonVal->AsNumber()); +} + +int64 UVaRestJsonValue::AsInt64() const +{ + if (!JsonVal.IsValid()) + { + ErrorMessage(TEXT("Number")); + return 0.f; + } + + return static_cast(JsonVal->AsNumber()); } FString UVaRestJsonValue::AsString() const @@ -233,7 +193,7 @@ UVaRestJsonObject* UVaRestJsonValue::AsObject() return nullptr; } - TSharedPtr NewObj = JsonVal->AsObject(); + const TSharedPtr NewObj = JsonVal->AsObject(); UVaRestJsonObject* JsonObj = NewObject(); JsonObj->SetRootObject(NewObj); diff --git a/Source/VaRest/Private/VaRestLibrary.cpp b/Source/VaRest/Private/VaRestLibrary.cpp index d241c00f..9c6f16f8 100644 --- a/Source/VaRest/Private/VaRestLibrary.cpp +++ b/Source/VaRest/Private/VaRestLibrary.cpp @@ -2,14 +2,19 @@ #include "VaRestLibrary.h" +#include "VaRest.h" #include "VaRestDefines.h" -#include "VaRestJsonObject.h" #include "VaRestRequestJSON.h" +#include "Engine/World.h" +#include "GenericPlatform/GenericPlatformHttp.h" +#include "Interfaces/IPluginManager.h" #include "Misc/Base64.h" -////////////////////////////////////////////////////////////////////////// -// Helpers +UVaRestSettings* UVaRestLibrary::GetVaRestSettings() +{ + return FVaRestModule::Get().GetSettings(); +} FString UVaRestLibrary::PercentEncode(const FString& Source) { @@ -18,12 +23,23 @@ FString UVaRestLibrary::PercentEncode(const FString& Source) FString UVaRestLibrary::Base64Encode(const FString& Source) { - return FBase64::Encode(Source); + TArray ByteArray; + const FTCHARToUTF8 StringSrc = FTCHARToUTF8(Source.GetCharArray().GetData()); + ByteArray.Append((uint8*)StringSrc.Get(), StringSrc.Length()); + + return FBase64::Encode(ByteArray); } bool UVaRestLibrary::Base64Decode(const FString& Source, FString& Dest) { - return FBase64::Decode(Source, Dest); + TArray ByteArray; + const bool Success = FBase64::Decode(Source, ByteArray); + + const FUTF8ToTCHAR StringSrc = FUTF8ToTCHAR((const ANSICHAR*)ByteArray.GetData(), ByteArray.Num()); + Dest = FString(); + Dest.AppendChars(StringSrc.Get(), StringSrc.Length()); + + return Success; } bool UVaRestLibrary::Base64EncodeData(const TArray& Data, FString& Dest) @@ -34,6 +50,7 @@ bool UVaRestLibrary::Base64EncodeData(const TArray& Data, FString& Dest) return true; } + Dest = FString(); return false; } @@ -41,3 +58,44 @@ bool UVaRestLibrary::Base64DecodeData(const FString& Source, TArray& Dest { return FBase64::Decode(Source, Dest); } + +FString UVaRestLibrary::StringToMd5(const FString& StringToHash) +{ + return FMD5::HashAnsiString(*StringToHash); +} + +FString UVaRestLibrary::StringToSha1(const FString& StringToHash) +{ + FSHA1 Sha1Gen; + + Sha1Gen.Update((unsigned char*)TCHAR_TO_ANSI(*StringToHash), FCString::Strlen(*StringToHash)); + Sha1Gen.Final(); + + FString Sha1String; + for (int32 i = 0; i < 20; i++) + { + Sha1String += FString::Printf(TEXT("%02x"), Sha1Gen.m_digest[i]); + } + + return Sha1String; +} + +FString UVaRestLibrary::GetVaRestVersion() +{ + const auto PluginRef = IPluginManager::Get().FindPlugin("VaRest"); + + return !PluginRef.IsValid() ? FString("invalid") : PluginRef->GetDescriptor().VersionName; +} + +FVaRestURL UVaRestLibrary::GetWorldURL(UObject* WorldContextObject) +{ + if (WorldContextObject) + { + if (UWorld* World = WorldContextObject->GetWorld()) + { + return FVaRestURL(World->URL); + } + } + + return FVaRestURL(); +} diff --git a/Source/VaRest/Private/VaRestRequestJSON.cpp b/Source/VaRest/Private/VaRestRequestJSON.cpp index 8b15c300..cbb68f50 100644 --- a/Source/VaRest/Private/VaRestRequestJSON.cpp +++ b/Source/VaRest/Private/VaRestRequestJSON.cpp @@ -4,13 +4,16 @@ #include "VaRestDefines.h" #include "VaRestJsonObject.h" +#include "VaRestJsonValue.h" #include "VaRestLibrary.h" #include "VaRestSettings.h" -#include "VaRestSubsystem.h" +#include "Engine/Engine.h" +#include "Engine/EngineTypes.h" +#include "Engine/LatentActionManager.h" +#include "Engine/World.h" +#include "Interfaces/IHttpResponse.h" #include "Json.h" -#include "Kismet/GameplayStatics.h" -#include "Misc/CoreMisc.h" #include "Runtime/Launch/Resources/Version.h" FString UVaRestRequestJSON::DeprecatedResponseString(TEXT("DEPRECATED: Please use GetResponseContentAsString() instead")); @@ -31,13 +34,13 @@ UVaRestRequestJSON::UVaRestRequestJSON(const class FObjectInitializer& PCIP) { ContinueAction = nullptr; - RequestVerb = ERequestVerb::GET; - RequestContentType = ERequestContentType::x_www_form_urlencoded_url; + RequestVerb = EVaRestRequestVerb::GET; + RequestContentType = EVaRestRequestContentType::x_www_form_urlencoded_url; ResetData(); } -void UVaRestRequestJSON::SetVerb(ERequestVerb Verb) +void UVaRestRequestJSON::SetVerb(EVaRestRequestVerb Verb) { RequestVerb = Verb; } @@ -47,7 +50,7 @@ void UVaRestRequestJSON::SetCustomVerb(FString Verb) CustomVerb = Verb; } -void UVaRestRequestJSON::SetContentType(ERequestContentType ContentType) +void UVaRestRequestJSON::SetContentType(EVaRestRequestContentType ContentType) { RequestContentType = ContentType; } @@ -110,6 +113,15 @@ void UVaRestRequestJSON::ResetResponseData() ResponseJsonObj = NewObject(); } + if (ResponseJsonValue != nullptr) + { + ResponseJsonValue->Reset(); + } + else + { + ResponseJsonValue = NewObject(); + } + ResponseHeaders.Empty(); ResponseCode = -1; ResponseSize = 0; @@ -164,6 +176,12 @@ void UVaRestRequestJSON::SetResponseObject(UVaRestJsonObject* JsonObject) ResponseJsonObj = JsonObject; } +UVaRestJsonValue* UVaRestRequestJSON::GetResponseValue() const +{ + check(ResponseJsonValue); + return ResponseJsonValue; +} + /////////////////////////////////////////////////////////////////////////// // Response data access @@ -172,9 +190,14 @@ FString UVaRestRequestJSON::GetURL() const return HttpRequest->GetURL(); } -ERequestStatus UVaRestRequestJSON::GetStatus() const +EVaRestRequestVerb UVaRestRequestJSON::GetVerb() const +{ + return RequestVerb; +} + +EVaRestRequestStatus UVaRestRequestJSON::GetStatus() const { - return ERequestStatus((uint8)HttpRequest->GetStatus()); + return EVaRestRequestStatus((uint8)HttpRequest->GetStatus()); } int32 UVaRestRequestJSON::GetResponseCode() const @@ -213,13 +236,8 @@ void UVaRestRequestJSON::SetURL(const FString& Url) // Be sure to trim URL because it can break links on iOS FString TrimmedUrl = Url; -#if ENGINE_MINOR_VERSION >= 18 TrimmedUrl.TrimStartInline(); TrimmedUrl.TrimEndInline(); -#else - TrimmedUrl.Trim(); - TrimmedUrl.TrimTrailing(); -#endif HttpRequest->SetURL(TrimmedUrl); } @@ -235,13 +253,8 @@ void UVaRestRequestJSON::ApplyURL(const FString& Url, UVaRestJsonObject*& Result // Be sure to trim URL because it can break links on iOS FString TrimmedUrl = Url; -#if ENGINE_MINOR_VERSION >= 18 TrimmedUrl.TrimStartInline(); TrimmedUrl.TrimEndInline(); -#else - TrimmedUrl.Trim(); - TrimmedUrl.TrimTrailing(); -#endif HttpRequest->SetURL(TrimmedUrl); @@ -279,23 +292,23 @@ void UVaRestRequestJSON::ProcessRequest() // Set verb switch (RequestVerb) { - case ERequestVerb::GET: + case EVaRestRequestVerb::GET: HttpRequest->SetVerb(TEXT("GET")); break; - case ERequestVerb::POST: + case EVaRestRequestVerb::POST: HttpRequest->SetVerb(TEXT("POST")); break; - case ERequestVerb::PUT: + case EVaRestRequestVerb::PUT: HttpRequest->SetVerb(TEXT("PUT")); break; - case ERequestVerb::DEL: + case EVaRestRequestVerb::DEL: HttpRequest->SetVerb(TEXT("DELETE")); break; - case ERequestVerb::CUSTOM: + case EVaRestRequestVerb::CUSTOM: HttpRequest->SetVerb(CustomVerb); break; @@ -306,7 +319,7 @@ void UVaRestRequestJSON::ProcessRequest() // Set content-type switch (RequestContentType) { - case ERequestContentType::x_www_form_urlencoded_url: + case EVaRestRequestContentType::x_www_form_urlencoded_url: { HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/x-www-form-urlencoded")); @@ -338,7 +351,7 @@ void UVaRestRequestJSON::ProcessRequest() } // Check extended log to avoid security vulnerability (#133) - if (GetSettings()->bExtendedLog) + if (UVaRestLibrary::GetVaRestSettings()->bExtendedLog) { UE_LOG(LogVaRest, Log, TEXT("%s: Request (urlencoded): %s %s %s %s"), *VA_FUNC_LINE, *HttpRequest->GetVerb(), *HttpRequest->GetURL(), *UrlParams, *StringRequestContent); } @@ -349,33 +362,41 @@ void UVaRestRequestJSON::ProcessRequest() break; } - case ERequestContentType::x_www_form_urlencoded_body: + case EVaRestRequestContentType::x_www_form_urlencoded_body: { HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/x-www-form-urlencoded")); FString UrlParams = ""; uint16 ParamIdx = 0; - // Loop through all the values and prepare additional url part - for (auto RequestIt = RequestJsonObj->GetRootObject()->Values.CreateIterator(); RequestIt; ++RequestIt) + // Add optional string content + if (!StringRequestContent.IsEmpty()) { - FString Key = RequestIt.Key(); - FString Value = RequestIt.Value().Get()->AsString(); - - if (!Key.IsEmpty() && !Value.IsEmpty()) + UrlParams = StringRequestContent; + } + else + { + // Loop through all the values and prepare additional url part + for (auto RequestIt = RequestJsonObj->GetRootObject()->Values.CreateIterator(); RequestIt; ++RequestIt) { - UrlParams += ParamIdx == 0 ? "" : "&"; - UrlParams += UVaRestLibrary::PercentEncode(Key) + "=" + UVaRestLibrary::PercentEncode(Value); - } + FString Key = RequestIt.Key(); + FString Value = RequestIt.Value().Get()->AsString(); - ParamIdx++; + if (!Key.IsEmpty() && !Value.IsEmpty()) + { + UrlParams += ParamIdx == 0 ? "" : "&"; + UrlParams += UVaRestLibrary::PercentEncode(Key) + "=" + UVaRestLibrary::PercentEncode(Value); + } + + ParamIdx++; + } } // Apply params HttpRequest->SetContentAsString(UrlParams); // Check extended log to avoid security vulnerability (#133) - if (GetSettings()->bExtendedLog) + if (UVaRestLibrary::GetVaRestSettings()->bExtendedLog) { UE_LOG(LogVaRest, Log, TEXT("%s: Request (url body): %s %s %s"), *VA_FUNC_LINE, *HttpRequest->GetVerb(), *HttpRequest->GetURL(), *UrlParams); } @@ -386,7 +407,7 @@ void UVaRestRequestJSON::ProcessRequest() break; } - case ERequestContentType::binary: + case EVaRestRequestContentType::binary: { HttpRequest->SetHeader(TEXT("Content-Type"), BinaryContentType); HttpRequest->SetContent(RequestBytes); @@ -395,10 +416,16 @@ void UVaRestRequestJSON::ProcessRequest() break; } - case ERequestContentType::json: + case EVaRestRequestContentType::json: { HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json")); + // Body is ignored for get requests, so we shouldn't place json into it even if it's empty + if (RequestVerb == EVaRestRequestVerb::GET) + { + break; + } + // Serialize data to json string FString OutputString; TSharedRef> Writer = TJsonWriterFactory<>::Create(&OutputString); @@ -407,7 +434,14 @@ void UVaRestRequestJSON::ProcessRequest() // Set Json content HttpRequest->SetContentAsString(OutputString); - UE_LOG(LogVaRest, Log, TEXT("Request (json): %s %s %sJSON(%s%s%s)JSON"), *HttpRequest->GetVerb(), *HttpRequest->GetURL(), LINE_TERMINATOR, LINE_TERMINATOR, *OutputString, LINE_TERMINATOR); + if (UVaRestLibrary::GetVaRestSettings()->bExtendedLog) + { + UE_LOG(LogVaRest, Log, TEXT("Request (json): %s %s %sJSON(%s%s%s)JSON"), *HttpRequest->GetVerb(), *HttpRequest->GetURL(), LINE_TERMINATOR, LINE_TERMINATOR, *OutputString, LINE_TERMINATOR); + } + else + { + UE_LOG(LogVaRest, Log, TEXT("Request (json): %s %s (check bExtendedLog for additional data)"), *HttpRequest->GetVerb(), *HttpRequest->GetURL()); + } break; } @@ -472,7 +506,7 @@ void UVaRestRequestJSON::OnProcessRequestComplete(FHttpRequestPtr Request, FHttp } } - if (GetSettings()->bUseChunkedParser) + if (UVaRestLibrary::GetVaRestSettings()->bUseChunkedParser) { // Try to deserialize data to JSON const TArray& Bytes = Response->GetContent(); @@ -489,12 +523,17 @@ void UVaRestRequestJSON::OnProcessRequestComplete(FHttpRequestPtr Request, FHttp else { // Use default unreal one - TSharedRef> Reader = TJsonReaderFactory<>::Create(*Response->GetContentAsString()); - TSharedPtr OutJsonObj; - if (FJsonSerializer::Deserialize(Reader, OutJsonObj)) + const TSharedRef> Reader = TJsonReaderFactory<>::Create(*Response->GetContentAsString()); + TSharedPtr OutJsonValue; + if (FJsonSerializer::Deserialize(Reader, OutJsonValue)) { - ResponseJsonObj->SetRootObject(OutJsonObj.ToSharedRef()); - ResponseSize = Response->GetContentLength(); + ResponseJsonValue->SetRootValue(OutJsonValue); + + if (ResponseJsonValue->GetType() == EVaJson::Object) + { + ResponseJsonObj->SetRootObject(ResponseJsonValue->GetRootValue()->AsObject()); + ResponseSize = Response->GetContentLength(); + } } } @@ -509,10 +548,8 @@ void UVaRestRequestJSON::OnProcessRequestComplete(FHttpRequestPtr Request, FHttp } // Broadcast the result events on next tick - AsyncTask(ENamedThreads::GameThread, [this]() { - OnRequestComplete.Broadcast(this); - OnStaticRequestComplete.Broadcast(this); - }); + OnRequestComplete.Broadcast(this); + OnStaticRequestComplete.Broadcast(this); // Finish the latent action if (ContinueAction) @@ -583,15 +620,3 @@ FString UVaRestRequestJSON::GetResponseContentAsString(bool bCacheResponseConten // Return previously cached content now return ResponseContent; } - -const UVaRestSettings* UVaRestRequestJSON::GetSettings() const -{ - auto GI = UGameplayStatics::GetGameInstance(this); - if (GI) - { - return GI->GetSubsystem()->GetSettings(); - } - - UE_LOG(LogVaRest, Warning, TEXT("%s: No World is provided for Outer object, Default settings will be used"), *VA_FUNC_LINE); - return GetDefault(); -} diff --git a/Source/VaRest/Private/VaRestSubsystem.cpp b/Source/VaRest/Private/VaRestSubsystem.cpp index e000da03..97daab65 100644 --- a/Source/VaRest/Private/VaRestSubsystem.cpp +++ b/Source/VaRest/Private/VaRestSubsystem.cpp @@ -4,16 +4,16 @@ #include "VaRestDefines.h" #include "VaRestJsonObject.h" -#include "VaRestSettings.h" +#include "VaRestJsonValue.h" -#include "Developer/Settings/Public/ISettingsModule.h" #include "Misc/FileHelper.h" #include "Misc/Paths.h" - -#define LOCTEXT_NAMESPACE "FVaRest" +#include "Serialization/JsonReader.h" +#include "Serialization/JsonSerializer.h" +#include "Subsystems/SubsystemBlueprintLibrary.h" UVaRestSubsystem::UVaRestSubsystem() - : UGameInstanceSubsystem() + : UEngineSubsystem() { } @@ -21,17 +21,6 @@ void UVaRestSubsystem::Initialize(FSubsystemCollectionBase& Collection) { Super::Initialize(Collection); - Settings = NewObject(GetTransientPackage(), "VaRestSettings", RF_Standalone); - - // Register settings - if (ISettingsModule* SettingsModule = FModuleManager::GetModulePtr("Settings")) - { - SettingsModule->RegisterSettings("Project", "Plugins", "VaRest", - LOCTEXT("RuntimeSettingsName", "VaRest"), - LOCTEXT("RuntimeSettingsDescription", "Configure VaRest plugin settings"), - Settings); - } - UE_LOG(LogVaRest, Log, TEXT("%s: VaRest subsystem initialized"), *VA_FUNC_LINE); } @@ -41,11 +30,8 @@ void UVaRestSubsystem::Deinitialize() Super::Deinitialize(); } -void UVaRestSubsystem::CallURL(const FString& URL, ERequestVerb Verb, ERequestContentType ContentType, UVaRestJsonObject* VaRestJson, const FVaRestCallDelegate& Callback) +void UVaRestSubsystem::CallURL(const FString& URL, EVaRestRequestVerb Verb, EVaRestRequestContentType ContentType, UVaRestJsonObject* VaRestJson, const FVaRestCallDelegate& Callback) { - UWorld* World = GetWorld(); - check(World); - // Check we have valid data json if (VaRestJson == nullptr) { @@ -78,7 +64,7 @@ void UVaRestSubsystem::OnCallComplete(UVaRestRequestJSON* Request) return; } - auto Response = RequestMap.Find(Request); + const auto Response = RequestMap.Find(Request); Request->OnStaticRequestComplete.Remove(Response->CompleteDelegateHandle); Request->OnStaticRequestFail.Remove(Response->FailDelegateHandle); @@ -92,7 +78,7 @@ UVaRestRequestJSON* UVaRestSubsystem::ConstructVaRestRequest() return NewObject(this); } -UVaRestRequestJSON* UVaRestSubsystem::ConstructVaRestRequestExt(ERequestVerb Verb, ERequestContentType ContentType) +UVaRestRequestJSON* UVaRestSubsystem::ConstructVaRestRequestExt(EVaRestRequestVerb Verb, EVaRestRequestContentType ContentType) { UVaRestRequestJSON* Request = ConstructVaRestRequest(); @@ -107,6 +93,105 @@ UVaRestJsonObject* UVaRestSubsystem::ConstructVaRestJsonObject() return NewObject(this); } +UVaRestJsonObject* UVaRestSubsystem::StaticConstructVaRestJsonObject() +{ + auto SelfSystem = CastChecked(USubsystemBlueprintLibrary::GetEngineSubsystem(UVaRestSubsystem::StaticClass()), ECastCheckedType::NullChecked); + return SelfSystem->ConstructVaRestJsonObject(); +} + +UVaRestJsonValue* UVaRestSubsystem::ConstructJsonValueNumber(float Number) +{ + TSharedPtr NewVal = MakeShareable(new FJsonValueNumber(Number)); + + UVaRestJsonValue* NewValue = NewObject(this); + NewValue->SetRootValue(NewVal); + + return NewValue; +} + +UVaRestJsonValue* UVaRestSubsystem::ConstructJsonValueString(const FString& StringValue) +{ + TSharedPtr NewVal = MakeShareable(new FJsonValueString(StringValue)); + + UVaRestJsonValue* NewValue = NewObject(this); + NewValue->SetRootValue(NewVal); + + return NewValue; +} + +UVaRestJsonValue* UVaRestSubsystem::ConstructJsonValueBool(bool InValue) +{ + TSharedPtr NewVal = MakeShareable(new FJsonValueBoolean(InValue)); + + UVaRestJsonValue* NewValue = NewObject(this); + NewValue->SetRootValue(NewVal); + + return NewValue; +} + +UVaRestJsonValue* UVaRestSubsystem::ConstructJsonValueArray(const TArray& InArray) +{ + // Prepare data array to create new value + TArray> ValueArray; + for (auto InVal : InArray) + { + ValueArray.Add(InVal->GetRootValue()); + } + + TSharedPtr NewVal = MakeShareable(new FJsonValueArray(ValueArray)); + + UVaRestJsonValue* NewValue = NewObject(this); + NewValue->SetRootValue(NewVal); + + return NewValue; +} + +UVaRestJsonValue* UVaRestSubsystem::ConstructJsonValueObject(UVaRestJsonObject* JsonObject) +{ + TSharedPtr NewVal = MakeShareable(new FJsonValueObject(JsonObject->GetRootObject())); + + UVaRestJsonValue* NewValue = NewObject(this); + NewValue->SetRootValue(NewVal); + + return NewValue; +} + +UVaRestJsonValue* UVaRestSubsystem::ConstructJsonValue(const TSharedPtr& InValue) +{ + TSharedPtr NewVal = InValue; + + UVaRestJsonValue* NewValue = NewObject(this); + NewValue->SetRootValue(NewVal); + + return NewValue; +} + +UVaRestJsonValue* UVaRestSubsystem::DecodeJsonValue(const FString& JsonString) +{ + const TSharedRef> Reader = TJsonReaderFactory<>::Create(*JsonString); + TSharedPtr OutJsonValue; + if (FJsonSerializer::Deserialize(Reader, OutJsonValue)) + { + return ConstructJsonValue(OutJsonValue); + } + + return nullptr; +} + +UVaRestJsonObject* UVaRestSubsystem::DecodeJsonObject(const FString& JsonString) +{ + const TSharedRef> Reader = TJsonReaderFactory<>::Create(*JsonString); + TSharedPtr OutJsonObj; + if (FJsonSerializer::Deserialize(Reader, OutJsonObj)) + { + auto NewJsonObj = NewObject(this); + NewJsonObj->SetRootObject(OutJsonObj); + return NewJsonObj; + } + + return nullptr; +} + class UVaRestJsonObject* UVaRestSubsystem::LoadJsonFromFile(const FString& Path, const bool bIsRelativeToContentDir) { auto* Json = ConstructVaRestJsonObject(); @@ -130,11 +215,3 @@ class UVaRestJsonObject* UVaRestSubsystem::LoadJsonFromFile(const FString& Path, return nullptr; } - -UVaRestSettings* UVaRestSubsystem::GetSettings() const -{ - check(Settings); - return Settings; -} - -#undef LOCTEXT_NAMESPACE diff --git a/Source/VaRest/Public/VaRest.h b/Source/VaRest/Public/VaRest.h index c5c37b63..86dade53 100644 --- a/Source/VaRest/Public/VaRest.h +++ b/Source/VaRest/Public/VaRest.h @@ -4,9 +4,15 @@ #include "Modules/ModuleManager.h" +class UVaRestSettings; + class FVaRestModule : public IModuleInterface { public: + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; + /** * Singleton-like access to this module's interface. This is just for convenience! * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. @@ -27,4 +33,11 @@ class FVaRestModule : public IModuleInterface { return FModuleManager::Get().IsModuleLoaded("VaRest"); } + + /** Getter for internal settings object to support runtime configuration changes */ + UVaRestSettings* GetSettings() const; + +protected: + /** Module settings */ + UVaRestSettings* ModuleSettings; }; diff --git a/Source/VaRest/Public/VaRestDefines.h b/Source/VaRest/Public/VaRestDefines.h index 6e2c698d..ec14ea47 100644 --- a/Source/VaRest/Public/VaRestDefines.h +++ b/Source/VaRest/Public/VaRestDefines.h @@ -4,25 +4,14 @@ #include "Runtime/Launch/Resources/Version.h" -#if ENGINE_MINOR_VERSION >= 15 #include "CoreMinimal.h" -#include "Engine/Engine.h" -#include "EngineDefines.h" -#include "UObject/Object.h" -#include "UObject/ScriptMacros.h" -#else -#include "CoreUObject.h" -#include "Engine.h" -#endif -#include "Delegates/DelegateCombinations.h" #include "Logging/LogCategory.h" #include "Logging/LogMacros.h" #include "Logging/LogVerbosity.h" // You should place include statements to your module's private header files here. You only need to // add includes for headers that are used in most of your module's source files though. -#include "Modules/ModuleManager.h" DECLARE_LOG_CATEGORY_EXTERN(LogVaRest, Log, All); diff --git a/Source/VaRest/Public/VaRestJsonObject.h b/Source/VaRest/Public/VaRestJsonObject.h index 89f5d2a5..eb176160 100644 --- a/Source/VaRest/Public/VaRestJsonObject.h +++ b/Source/VaRest/Public/VaRestJsonObject.h @@ -2,7 +2,10 @@ #pragma once +#include "VaRestDefines.h" + #include "Dom/JsonObject.h" +#include "Templates/UnrealTypeTraits.h" #include "VaRestJsonObject.generated.h" @@ -16,6 +19,7 @@ class VAREST_API UVaRestJsonObject : public UObject { GENERATED_UCLASS_BODY() +public: /** Reset all internal data */ UFUNCTION(BlueprintCallable, Category = "VaRest|Json") void Reset(); @@ -97,6 +101,14 @@ class VAREST_API UVaRestJsonObject : public UObject UFUNCTION(BlueprintCallable, Category = "VaRest|Json") void SetIntegerField(const FString& FieldName, int32 Number); + /** Get the field named FieldName as an Int64. Ensures that the field is present and is of type Json number. */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + int64 GetInt64Field(const FString& FieldName) const; + + /** Add a field named FieldName with Int64 as value. */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + void SetInt64Field(const FString& FieldName, int64 Number); + /** Get the field named FieldName as a string. */ UFUNCTION(BlueprintCallable, Category = "VaRest|Json") FString GetStringField(const FString& FieldName) const; @@ -121,14 +133,84 @@ class VAREST_API UVaRestJsonObject : public UObject UFUNCTION(BlueprintCallable, Category = "VaRest|Json") void SetObjectField(const FString& FieldName, UVaRestJsonObject* JsonObject); + /** Set a map of fields with String values */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + void SetMapFields_string(const TMap& Fields); + + /** Set a map of fields with uint8 values */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + void SetMapFields_uint8(const TMap& Fields); + + /** Set a map of fields with int32 values */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + void SetMapFields_int32(const TMap& Fields); + + /** Set a map of fields with int64 values */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + void SetMapFields_int64(const TMap& Fields); + + /** Set a map of fields with bool values */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + void SetMapFields_bool(const TMap& Fields); + +private: + /** Internal implementation for setting map fields. */ + template + void SetMapFields_Impl(const TMap& Fields) + { + for (auto& field : Fields) + { + // No need to support all int types as they're not supported by BP + if (TIsSame::Value || TIsSame::Value || TIsSame::Value || TIsSame::Value) + { + SetNumberField(field.Key, field.Value); + } + else if (TIsSame::Value) + { + SetBoolField(field.Key, (bool)field.Value); + } + } + } + + /** Internal implementation to get number arrays of different types */ + template + TArray GetTypeArrayField(const FString& FieldName) const + { + TArray NumberArray; + if (!JsonObj->HasTypedField(FieldName) || FieldName.IsEmpty()) + { + UE_LOG(LogVaRest, Warning, TEXT("%s: No field with name %s of type Array"), *VA_FUNC_LINE, *FieldName); + return NumberArray; + } + + const TArray> JsonArrayValues = JsonObj->GetArrayField(FieldName); + for (TArray>::TConstIterator It(JsonArrayValues); It; ++It) + { + const auto Value = (*It).Get(); + if (Value->Type != EJson::Number) + { + UE_LOG(LogVaRest, Error, TEXT("Not Number element in array with field name %s"), *FieldName); + } + + NumberArray.Add((*It)->AsNumber()); + } + + return NumberArray; + } + ////////////////////////////////////////////////////////////////////////// // Array fields helpers (uniform arrays) +public: /** Get the field named FieldName as a Number Array. Use it only if you're sure that array is uniform! * Attn.!! float used instead of double to make the function blueprintable! */ UFUNCTION(BlueprintCallable, Category = "VaRest|Json") TArray GetNumberArrayField(const FString& FieldName) const; + /** Get the field named FieldName as a Number Array. Use it only if you're sure that array is uniform! */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + TArray GetIntegerArrayField(const FString& FieldName) const; + /** Set an ObjectField named FieldName and value of Number Array * Attn.!! float used instead of double to make the function blueprintable! */ UFUNCTION(BlueprintCallable, Category = "VaRest|Json") @@ -176,7 +258,7 @@ class VAREST_API UVaRestJsonObject : public UObject public: /** Save json to file */ - bool WriteToFile(const FString& Path); + bool WriteToFile(const FString& Path) const; /** * Blueprint Save json to filepath diff --git a/Source/VaRest/Public/VaRestJsonValue.h b/Source/VaRest/Public/VaRestJsonValue.h index 1d9ad0f3..45ba8b40 100644 --- a/Source/VaRest/Public/VaRestJsonValue.h +++ b/Source/VaRest/Public/VaRestJsonValue.h @@ -2,8 +2,6 @@ #pragma once -#include "VaRestDefines.h" - #include "VaRestJsonValue.generated.h" class UVaRestJsonObject; @@ -32,29 +30,10 @@ class VAREST_API UVaRestJsonValue : public UObject { GENERATED_UCLASS_BODY() - /** Create new Json Number value - * Attn.!! float used instead of double to make the function blueprintable! */ - UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Number Value", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "VaRest|Json") - static UVaRestJsonValue* ConstructJsonValueNumber(UObject* WorldContextObject, float Number); - - /** Create new Json String value */ - UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json String Value", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "VaRest|Json") - static UVaRestJsonValue* ConstructJsonValueString(UObject* WorldContextObject, const FString& StringValue); - - /** Create new Json Bool value */ - UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Bool Value", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "VaRest|Json") - static UVaRestJsonValue* ConstructJsonValueBool(UObject* WorldContextObject, bool InValue); - - /** Create new Json Array value */ - UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Array Value", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "VaRest|Json") - static UVaRestJsonValue* ConstructJsonValueArray(UObject* WorldContextObject, const TArray& InArray); - - /** Create new Json Object value */ - UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Object Value", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject"), Category = "VaRest|Json") - static UVaRestJsonValue* ConstructJsonValueObject(UObject* WorldContextObject, UVaRestJsonObject* JsonObject); - - /** Create new Json value from FJsonValue (to be used from VaRestJsonObject) */ - static UVaRestJsonValue* ConstructJsonValue(UObject* WorldContextObject, const TSharedPtr& InValue); +public: + /** Reset all internal data */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + void Reset(); /** Get the root Json value */ TSharedPtr& GetRootValue(); @@ -66,28 +45,36 @@ class VAREST_API UVaRestJsonValue : public UObject // FJsonValue API /** Get type of Json value (Enum) */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + UFUNCTION(BlueprintPure, Category = "VaRest|Json") EVaJson GetType() const; /** Get type of Json value (String) */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + UFUNCTION(BlueprintPure, Category = "VaRest|Json") FString GetTypeString() const; /** Returns true if this value is a 'null' */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + UFUNCTION(BlueprintPure, Category = "VaRest|Json") bool IsNull() const; /** Returns this value as a double, throwing an error if this is not an Json Number * Attn.!! float used instead of double to make the function blueprintable! */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + UFUNCTION(BlueprintPure, Category = "VaRest|Json") float AsNumber() const; - /** Returns this value as a number, throwing an error if this is not an Json String */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + /** Returns this value as a int32, throwing an error if this is not an Json Number */ + UFUNCTION(BlueprintPure, Category = "VaRest|Json") + int32 AsInt32() const; + + /** Returns this value as a int64, throwing an error if this is not an Json Number */ + UFUNCTION(BlueprintPure, Category = "VaRest|Json") + int64 AsInt64() const; + + /** Returns this value as a string, throwing an error if this is not an Json String */ + UFUNCTION(BlueprintPure, Category = "VaRest|Json") FString AsString() const; /** Returns this value as a boolean, throwing an error if this is not an Json Bool */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Json") + UFUNCTION(BlueprintPure, Category = "VaRest|Json") bool AsBool() const; /** Returns this value as an array, throwing an error if this is not an Json Array */ diff --git a/Source/VaRest/Public/VaRestLibrary.h b/Source/VaRest/Public/VaRestLibrary.h index 0ef6323f..11977073 100644 --- a/Source/VaRest/Public/VaRestLibrary.h +++ b/Source/VaRest/Public/VaRestLibrary.h @@ -4,11 +4,12 @@ #include "Kismet/BlueprintFunctionLibrary.h" -#include "VaRestDefines.h" #include "VaRestTypes.h" #include "VaRestLibrary.generated.h" +class UVaRestSettings; + /** * Useful tools for REST communications */ @@ -17,6 +18,13 @@ class VAREST_API UVaRestLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() + ////////////////////////////////////////////////////////////////////////// + // Data Accessors +public: + /** Direct access to the plugin settings */ + UFUNCTION(BlueprintPure, Category = "VaRest|Common") + static UVaRestSettings* GetVaRestSettings(); + ////////////////////////////////////////////////////////////////////////// // Helpers @@ -62,4 +70,40 @@ class VAREST_API UVaRestLibrary : public UBlueprintFunctionLibrary */ UFUNCTION(BlueprintCallable, Category = "VaRest|Utility", meta = (DisplayName = "Base64 Decode Data")) static bool Base64DecodeData(const FString& Source, TArray& Dest); + + /** + * Helper to perform the very common case of hashing an ASCII string into a hex representation. + * + * @param String Hex representation of the hash (32 lower-case hex digits) + */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Utility", meta = (DisplayName = "String to MD5")) + static FString StringToMd5(const FString& StringToHash); + + /** + * Helper to perform the SHA1 hash operation on string. + */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Utility", meta = (DisplayName = "String to SHA1")) + static FString StringToSha1(const FString& StringToHash); + + /** + * Helper method to convert a status code from HTTP to an enum for easier readability + */ + UFUNCTION(BlueprintPure, Category = "VaRest|Utility", meta = (DisplayName = "HTTP Status Int To Enum")) + static FORCEINLINE EVaRestHttpStatusCode::Type HTTPStatusIntToEnum(int32 StatusCode) { return (EVaRestHttpStatusCode::Type)StatusCode; } + + /** + * Get the plugin's version + */ + UFUNCTION(BlueprintPure, Category = "VaRest|Utility", meta = (DisplayName = "Get VaRest Version")) + static FString GetVaRestVersion(); + + ////////////////////////////////////////////////////////////////////////// + // Common Network Helpers + +public: + /** + * Get the URL that was used when loading this World + */ + UFUNCTION(BlueprintPure, Category = "VaRest|Utility", meta = (WorldContext = "WorldContextObject")) + static FVaRestURL GetWorldURL(UObject* WorldContextObject); }; diff --git a/Source/VaRest/Public/VaRestRequestJSON.h b/Source/VaRest/Public/VaRestRequestJSON.h index 4d643d65..5f65d1b2 100644 --- a/Source/VaRest/Public/VaRestRequestJSON.h +++ b/Source/VaRest/Public/VaRestRequestJSON.h @@ -4,12 +4,16 @@ #include "Engine/LatentActionManager.h" #include "Http.h" +#include "HttpModule.h" +#include "Interfaces/IHttpRequest.h" #include "LatentActions.h" #include "VaRestTypes.h" #include "VaRestRequestJSON.generated.h" +class UVaRestJsonValue; +class UVaRestJsonObject; class UVaRestSettings; /** @@ -89,7 +93,7 @@ class VAREST_API UVaRestRequestJSON : public UObject /** Set verb to the request */ UFUNCTION(BlueprintCallable, Category = "VaRest|Request") - void SetVerb(ERequestVerb Verb); + void SetVerb(EVaRestRequestVerb Verb); /** Set custom verb to the request */ UFUNCTION(BlueprintCallable, Category = "VaRest|Request") @@ -98,7 +102,7 @@ class VAREST_API UVaRestRequestJSON : public UObject /** Set content type to the request. If you're using the x-www-form-urlencoded, * params/constaints should be defined as key=ValueString pairs from Json data */ UFUNCTION(BlueprintCallable, Category = "VaRest|Request") - void SetContentType(ERequestContentType ContentType); + void SetContentType(EVaRestRequestContentType ContentType); /** Set content type of the request for binary post data */ UFUNCTION(BlueprintCallable, Category = "VaRest|Request") @@ -154,19 +158,27 @@ class VAREST_API UVaRestRequestJSON : public UObject UFUNCTION(BlueprintCallable, Category = "VaRest|Response") void SetResponseObject(UVaRestJsonObject* JsonObject); + /** Get the Response Json value */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Response") + UVaRestJsonValue* GetResponseValue() const; + /////////////////////////////////////////////////////////////////////////// // Request/response data access /** Get url of http request */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Request") + UFUNCTION(BlueprintPure, Category = "VaRest|Request") FString GetURL() const; + /** Get verb to the request */ + UFUNCTION(BlueprintPure, Category = "VaRest|Request") + EVaRestRequestVerb GetVerb() const; + /** Get status of http request */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Request") - ERequestStatus GetStatus() const; + UFUNCTION(BlueprintPure, Category = "VaRest|Request") + EVaRestRequestStatus GetStatus() const; /** Get the response code of the last query */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Response") + UFUNCTION(BlueprintPure, Category = "VaRest|Response") int32 GetResponseCode() const; /** Get value of desired response header */ @@ -174,7 +186,7 @@ class VAREST_API UVaRestRequestJSON : public UObject FString GetResponseHeader(const FString& HeaderName); /** Get list of all response headers */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Response") + UFUNCTION(BlueprintPure, Category = "VaRest|Response") TArray GetAllResponseHeaders() const; ////////////////////////////////////////////////////////////////////////// @@ -294,11 +306,15 @@ class VAREST_API UVaRestRequestJSON : public UObject UPROPERTY() UVaRestJsonObject* ResponseJsonObj; + /** Response data stored as JSON value */ + UPROPERTY() + UVaRestJsonValue* ResponseJsonValue; + /** Verb for making request (GET,POST,etc) */ - ERequestVerb RequestVerb; + EVaRestRequestVerb RequestVerb; /** Content type to be applied for request */ - ERequestContentType RequestContentType; + EVaRestRequestContentType RequestContentType; /** Mapping of header section to values. Used to generate final header string for request */ TMap RequestHeaders; @@ -313,12 +329,9 @@ class VAREST_API UVaRestRequestJSON : public UObject FString CustomVerb; /** Request we're currently processing */ - TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); + TSharedRef HttpRequest = FHttpModule::Get().CreateRequest(); public: /** Returns reference to internal request object */ - TSharedRef GetHttpRequest() const { return HttpRequest; }; - - /** Helper function to get runtime settings */ - const UVaRestSettings* GetSettings() const; + TSharedRef GetHttpRequest() const { return HttpRequest; }; }; diff --git a/Source/VaRest/Public/VaRestSubsystem.h b/Source/VaRest/Public/VaRestSubsystem.h index 89fdd36a..3fae927e 100644 --- a/Source/VaRest/Public/VaRestSubsystem.h +++ b/Source/VaRest/Public/VaRestSubsystem.h @@ -2,17 +2,14 @@ #pragma once +#include "VaRestJsonObject.h" +#include "VaRestJsonValue.h" #include "VaRestRequestJSON.h" -#include "Delegates/DelegateCombinations.h" -#include "Subsystems/GameInstanceSubsystem.h" -#include "Subsystems/SubsystemCollection.h" +#include "Subsystems/EngineSubsystem.h" #include "VaRestSubsystem.generated.h" -class UVaRestRequestJSON; -class UVaRestSettings; - DECLARE_DYNAMIC_DELEGATE_OneParam(FVaRestCallDelegate, UVaRestRequestJSON*, Request); USTRUCT() @@ -36,7 +33,7 @@ struct FVaRestCallResponse }; UCLASS() -class VAREST_API UVaRestSubsystem : public UGameInstanceSubsystem +class VAREST_API UVaRestSubsystem : public UEngineSubsystem { GENERATED_BODY() @@ -54,7 +51,7 @@ class VAREST_API UVaRestSubsystem : public UGameInstanceSubsystem public: /** Easy way to process http requests */ UFUNCTION(BlueprintCallable, Category = "VaRest|Utility") - void CallURL(const FString& URL, ERequestVerb Verb, ERequestContentType ContentType, UVaRestJsonObject* VaRestJson, const FVaRestCallDelegate& Callback); + void CallURL(const FString& URL, EVaRestRequestVerb Verb, EVaRestRequestContentType ContentType, UVaRestJsonObject* VaRestJson, const FVaRestCallDelegate& Callback); /** Called when URL is processed (one for both success/unsuccess events)*/ void OnCallComplete(UVaRestRequestJSON* Request); @@ -73,32 +70,60 @@ class VAREST_API UVaRestSubsystem : public UGameInstanceSubsystem /** Creates new request with defined verb and content type */ UFUNCTION(BlueprintCallable, meta = (DisplayName = "Construct Json Request"), Category = "VaRest|Subsystem") - UVaRestRequestJSON* ConstructVaRestRequestExt(ERequestVerb Verb, ERequestContentType ContentType); + UVaRestRequestJSON* ConstructVaRestRequestExt(EVaRestRequestVerb Verb, EVaRestRequestContentType ContentType); /** Create new Json object */ UFUNCTION(BlueprintCallable, meta = (DisplayName = "Construct Json Object"), Category = "VaRest|Subsystem") UVaRestJsonObject* ConstructVaRestJsonObject(); + /** Create new Json object (static one for MakeJson node, hack for #293) */ + UFUNCTION() + static UVaRestJsonObject* StaticConstructVaRestJsonObject(); + + /** Create new Json Number value + * Attn.!! float used instead of double to make the function blueprintable! */ + UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Number Value"), Category = "VaRest|Subsystem") + UVaRestJsonValue* ConstructJsonValueNumber(float Number); + + /** Create new Json String value */ + UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json String Value"), Category = "VaRest|Subsystem") + UVaRestJsonValue* ConstructJsonValueString(const FString& StringValue); + + /** Create new Json Bool value */ + UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Bool Value"), Category = "VaRest|Subsystem") + UVaRestJsonValue* ConstructJsonValueBool(bool InValue); + + /** Create new Json Array value */ + UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Array Value"), Category = "VaRest|Subsystem") + UVaRestJsonValue* ConstructJsonValueArray(const TArray& InArray); + + /** Create new Json Object value */ + UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct Json Object Value"), Category = "VaRest|Subsystem") + UVaRestJsonValue* ConstructJsonValueObject(UVaRestJsonObject* JsonObject); + + /** Create new Json value from FJsonValue (to be used from VaRestJsonObject) */ + UVaRestJsonValue* ConstructJsonValue(const TSharedPtr& InValue); + + ////////////////////////////////////////////////////////////////////////// + // Serialization + +public: + /** Construct Json value from string */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Subsystem") + UVaRestJsonValue* DecodeJsonValue(const FString& JsonString); + + /** Construct Json object from string */ + UFUNCTION(BlueprintCallable, Category = "VaRest|Subsystem") + UVaRestJsonObject* DecodeJsonObject(const FString& JsonString); + ////////////////////////////////////////////////////////////////////////// // File system integration public: - /** + /** * Load JSON from formatted text file * @param bIsRelativeToContentDir if set to 'false' path is treated as absolute */ UFUNCTION(BlueprintCallable, Category = "VaRest|Utility") - class UVaRestJsonObject* LoadJsonFromFile(const FString& Path, const bool bIsRelativeToContentDir = true); - - ////////////////////////////////////////////////////////////////////////// - // Data getters and helpers - -public: - /** Getter for internal settings object to support runtime configuration changes */ - UFUNCTION(BlueprintCallable, Category = "VaRest|Subsystem") - UVaRestSettings* GetSettings() const; - -private: - /** Plugin settings */ - UVaRestSettings* Settings; + UVaRestJsonObject* LoadJsonFromFile(const FString& Path, const bool bIsRelativeToContentDir = true); }; diff --git a/Source/VaRest/Public/VaRestTypes.h b/Source/VaRest/Public/VaRestTypes.h index 5088e60c..fbbf94ae 100644 --- a/Source/VaRest/Public/VaRestTypes.h +++ b/Source/VaRest/Public/VaRestTypes.h @@ -2,9 +2,13 @@ #pragma once +#include "Engine/EngineBaseTypes.h" + +#include "VaRestTypes.generated.h" + /** Verb (GET, PUT, POST) used by the request */ UENUM(BlueprintType) -enum class ERequestVerb : uint8 +enum class EVaRestRequestVerb : uint8 { GET, POST, @@ -17,7 +21,7 @@ enum class ERequestVerb : uint8 // clang-format off /** Content type (json, urlencoded, etc.) used by the request */ UENUM(BlueprintType) -enum class ERequestContentType : uint8 +enum class EVaRestRequestContentType : uint8 { x_www_form_urlencoded_url UMETA(DisplayName = "x-www-form-urlencoded (URL)"), x_www_form_urlencoded_body UMETA(DisplayName = "x-www-form-urlencoded (Request Body)"), @@ -28,7 +32,7 @@ enum class ERequestContentType : uint8 /** Enumerates the current state of an Http request */ UENUM(BlueprintType) -enum class ERequestStatus : uint8 +enum class EVaRestRequestStatus : uint8 { /** Has not been started via ProcessRequest() */ NotStarted, @@ -41,3 +45,155 @@ enum class ERequestStatus : uint8 /** Finished and was successful */ Succeeded }; + +// Taken from Interfaces/IHttpResponse.h (had to make BlueprintType :/) +UENUM(BlueprintType) +namespace EVaRestHttpStatusCode +{ +/** + * Response codes that can come back from an Http request + */ +enum Type +{ + // status code not set yet + Unknown = 0 UMETA(DisplayName = "Unknown = 0"), + // the request can be continued. + Continue = 100 UMETA(DisplayName = "Continue = 100"), + // the server has switched protocols in an upgrade header. + SwitchProtocol = 101 UMETA(DisplayName = "SwitchProtocol = 101"), + // the request completed successfully. + Ok = 200 UMETA(DisplayName = "Ok = 200"), + // the request has been fulfilled and resulted in the creation of a new resource. + Created = 201 UMETA(DisplayName = "Created = 201"), + // the request has been accepted for processing, but the processing has not been completed. + Accepted = 202 UMETA(DisplayName = "Accepted = 202"), + // the returned meta information in the entity-header is not the definitive set available from the origin server. + Partial = 203 UMETA(DisplayName = "Partial = 203"), + // the server has fulfilled the request, but there is no new information to send back. + NoContent = 204 UMETA(DisplayName = "NoContent = 204"), + // the request has been completed, and the client program should reset the document view that caused the request to be sent to allow the user to easily initiate another input action. + ResetContent = 205 UMETA(DisplayName = "ResetContent = 205"), + // the server has fulfilled the partial get request for the resource. + PartialContent = 206 UMETA(DisplayName = "PartialContent = 206"), + // the server couldn't decide what to return. + Ambiguous = 300 UMETA(DisplayName = "Ambiguous = 300"), + // the requested resource has been assigned to a new permanent uri (uniform resource identifier), and any future references to this resource should be done using one of the returned uris. + Moved = 301 UMETA(DisplayName = "Moved = 301"), + // the requested resource resides temporarily under a different uri (uniform resource identifier). + Redirect = 302 UMETA(DisplayName = "Redirect = 302"), + // the response to the request can be found under a different uri (uniform resource identifier) and should be retrieved using a get http verb on that resource. + RedirectMethod = 303 UMETA(DisplayName = "RedirectMethod = 303"), + // the requested resource has not been modified. + NotModified = 304 UMETA(DisplayName = "NotModified = 304"), + // the requested resource must be accessed through the proxy given by the location field. + UseProxy = 305 UMETA(DisplayName = "UseProxy = 305"), + // the redirected request keeps the same http verb. http/1.1 behavior. + RedirectKeepVerb = 307 UMETA(DisplayName = "RedirectKeepVerb = 307"), + // the request could not be processed by the server due to invalid syntax. + BadRequest = 400 UMETA(DisplayName = "BadRequest = 400"), + // the requested resource requires user authentication. + Denied = 401 UMETA(DisplayName = "Denied = 401"), + // not currently implemented in the http protocol. + PaymentReq = 402 UMETA(DisplayName = "PaymentReq = 402"), + // the server understood the request, but is refusing to fulfill it. + Forbidden = 403 UMETA(DisplayName = "Forbidden = 403"), + // the server has not found anything matching the requested uri (uniform resource identifier). + NotFound = 404 UMETA(DisplayName = "NotFound = 404"), + // the http verb used is not allowed. + BadMethod = 405 UMETA(DisplayName = "BadMethod = 405"), + // no responses acceptable to the client were found. + NoneAcceptable = 406 UMETA(DisplayName = "NoneAcceptable = 406"), + // proxy authentication required. + ProxyAuthReq = 407 UMETA(DisplayName = "ProxyAuthReq = 407"), + // the server timed out waiting for the request. + RequestTimeout = 408 UMETA(DisplayName = "RequestTimeout = 408"), + // the request could not be completed due to a conflict with the current state of the resource. the user should resubmit with more information. + Conflict = 409 UMETA(DisplayName = "Conflict = 409"), + // the requested resource is no longer available at the server, and no forwarding address is known. + Gone = 410 UMETA(DisplayName = "Gone = 410"), + // the server refuses to accept the request without a defined content length. + LengthRequired = 411 UMETA(DisplayName = "LengthRequired = 411"), + // the precondition given in one or more of the request header fields evaluated to false when it was tested on the server. + PrecondFailed = 412 UMETA(DisplayName = "PrecondFailed = 412"), + // the server is refusing to process a request because the request entity is larger than the server is willing or able to process. + RequestTooLarge = 413 UMETA(DisplayName = "RequestTooLarge = 413"), + // the server is refusing to service the request because the request uri (uniform resource identifier) is longer than the server is willing to interpret. + UriTooLong = 414 UMETA(DisplayName = "UriTooLong = 414"), + // the server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method. + UnsupportedMedia = 415 UMETA(DisplayName = "UnsupportedMedia = 415"), + // too many requests, the server is throttling + TooManyRequests = 429 UMETA(DisplayName = "TooManyRequests = 429"), + // the request should be retried after doing the appropriate action. + RetryWith = 449 UMETA(DisplayName = "RetryWith = 449"), + // the server encountered an unexpected condition that prevented it from fulfilling the request. + ServerError = 500 UMETA(DisplayName = "ServerError = 500"), + // the server does not support the functionality required to fulfill the request. + NotSupported = 501 UMETA(DisplayName = "NotSupported = 501"), + // the server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request. + BadGateway = 502 UMETA(DisplayName = "BadGateway = 502"), + // the service is temporarily overloaded. + ServiceUnavail = 503 UMETA(DisplayName = "ServiceUnavail = 503"), + // the request was timed out waiting for a gateway. + GatewayTimeout = 504 UMETA(DisplayName = "GatewayTimeout = 504"), + // the server does not support, or refuses to support, the http protocol version that was used in the request message. + VersionNotSup = 505 UMETA(DisplayName = "VersionNotSup = 505") +}; +} // namespace EVaRestHttpStatusCode + +/** + * FURL structure wrapper for BP access + */ +USTRUCT(BlueprintType) +struct VAREST_API FVaRestURL +{ + GENERATED_BODY() + + /** Protocol, i.e. "unreal" or "http" */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "URL") + FString Protocol; + + /** Optional hostname, i.e. "204.157.115.40" or "unreal.epicgames.com", blank if local. */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "URL") + FString Host; + + /** Optional host port */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "URL") + int32 Port; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "URL") + int32 Valid; + + /** Map name, i.e. "SkyCity", default is "Entry" */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "URL") + FString Map; + + /** Optional place to download Map if client does not possess it */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "URL") + FString RedirectURL; + + /** Options */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "URL") + TArray Op; + + /** Portal to enter through, default is "" */ + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "URL") + FString Portal; + + FVaRestURL() + : Port(0) + , Valid(0) + { + } + + FVaRestURL(FURL& InUrl) + : Protocol(InUrl.Protocol) + , Host(InUrl.Host) + , Port(InUrl.Port) + , Valid(InUrl.Valid) + , Map(InUrl.Map) + , RedirectURL(InUrl.RedirectURL) + , Op(InUrl.Op) + , Portal(InUrl.Portal) + { + } +}; diff --git a/Source/VaRest/VaRest.Build.cs b/Source/VaRest/VaRest.Build.cs index 30d13a99..fb860832 100644 --- a/Source/VaRest/VaRest.Build.cs +++ b/Source/VaRest/VaRest.Build.cs @@ -9,6 +9,7 @@ public class VaRest : ModuleRules public VaRest(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + PrecompileForTargets = PrecompileTargetsType.Any; PrivateIncludePaths.AddRange( new string[] { @@ -23,7 +24,8 @@ public VaRest(ReadOnlyTargetRules Target) : base(Target) "CoreUObject", "Engine", "HTTP", - "Json" + "Json", + "Projects" // Required by IPluginManager etc (used to get plugin information) // ... add other public dependencies that you statically link with here ... }); } diff --git a/Source/VaRestEditor/Private/VaRestEditor.cpp b/Source/VaRestEditor/Private/VaRestEditor.cpp index 82d0973e..c3bb7d07 100644 --- a/Source/VaRestEditor/Private/VaRestEditor.cpp +++ b/Source/VaRestEditor/Private/VaRestEditor.cpp @@ -2,6 +2,8 @@ #include "VaRestEditor.h" +#include "Modules/ModuleManager.h" + #define LOCTEXT_NAMESPACE "FVaRestEditorModule" void FVaRestEditorModule::StartupModule() diff --git a/Source/VaRestEditor/Private/VaRest_BreakJson.cpp b/Source/VaRestEditor/Private/VaRest_BreakJson.cpp index b61f76af..4083062c 100644 --- a/Source/VaRestEditor/Private/VaRest_BreakJson.cpp +++ b/Source/VaRestEditor/Private/VaRest_BreakJson.cpp @@ -26,7 +26,7 @@ class FKCHandler_BreakJson : public FNodeHandlingFunctor virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override { - UEdGraphPin* InputPin = NULL; + UEdGraphPin* InputPin = nullptr; for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex) { @@ -39,7 +39,7 @@ class FKCHandler_BreakJson : public FNodeHandlingFunctor } UEdGraphPin* InNet = FEdGraphUtilities::GetNetFromPin(InputPin); - UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRest.VaRestJsonObject'"))); + UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), nullptr, TEXT("class'VaRest.VaRestJsonObject'"))); FBPTerminal** SourceTerm = Context.NetMap.Find(InNet); if (SourceTerm == nullptr) @@ -59,34 +59,20 @@ class FKCHandler_BreakJson : public FNodeHandlingFunctor FBPTerminal** Target = Context.NetMap.Find(Pin); -#if ENGINE_MINOR_VERSION >= 19 const FName& FieldName = Pin->PinName; const FName& FieldType = Pin->PinType.PinCategory; -#else - const FString& FieldName = Pin->PinName; - const FString& FieldType = Pin->PinType.PinCategory; -#endif FBPTerminal* FieldNameTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal); FieldNameTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_String; -#if ENGINE_MINOR_VERSION >= 13 FieldNameTerm->SourcePin = Pin; -#else - FieldNameTerm->Source = Pin; -#endif -#if ENGINE_MINOR_VERSION >= 19 FieldNameTerm->Name = FieldName.ToString(); FieldNameTerm->TextLiteral = FText::FromName(FieldName); -#else - FieldNameTerm->Name = FieldName; - FieldNameTerm->TextLiteral = FText::FromString(FieldName); -#endif FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node); FName FunctionName; - bool bIsArray = Pin->PinType.ContainerType == EPinContainerType::Array; + const bool bIsArray = Pin->PinType.ContainerType == EPinContainerType::Array; if (FieldType == CompilerContext.GetSchema()->PC_Boolean) { FunctionName = bIsArray ? TEXT("GetBoolArrayField") : TEXT("GetBoolField"); @@ -122,7 +108,7 @@ class FKCHandler_BreakJson : public FNodeHandlingFunctor FBPTerminal* RegisterInputTerm(FKismetFunctionContext& Context, UVaRest_BreakJson* Node) { // Find input pin - UEdGraphPin* InputPin = NULL; + UEdGraphPin* InputPin = nullptr; for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex) { UEdGraphPin* Pin = Node->Pins[PinIndex]; @@ -168,7 +154,7 @@ class FKCHandler_BreakJson : public FNodeHandlingFunctor for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex) { UEdGraphPin* Pin = Node->Pins[PinIndex]; - if (NULL != Pin && EGPD_Output == Pin->Direction) + if (nullptr != Pin && EGPD_Output == Pin->Direction) { RegisterOutputTerm(Context, Pin, StructContextTerm); } @@ -194,14 +180,10 @@ void UVaRest_BreakJson::AllocateDefaultPins() { const UEdGraphSchema_K2* K2Schema = GetDefault(); - UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRest.VaRestJsonObject'"))); + UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), nullptr, TEXT("class'VaRest.VaRestJsonObject'"))); UEdGraphPin* Pin = CreatePin(EGPD_Input, K2Schema->PC_Object, TEXT(""), Class, TEXT("Target")); -#if ENGINE_MINOR_VERSION >= 17 K2Schema->SetPinAutogeneratedDefaultValueBasedOnType(Pin); -#else - K2Schema->SetPinDefaultValueBasedOnType(Pin); -#endif CreateProjectionPins(Pin); } @@ -213,7 +195,7 @@ FLinearColor UVaRest_BreakJson::GetNodeTitleColor() const void UVaRest_BreakJson::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) { - FName PropertyName = (PropertyChangedEvent.Property != NULL) ? PropertyChangedEvent.Property->GetFName() : NAME_None; + const FName PropertyName = (PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None; if (PropertyName == GET_MEMBER_NAME_STRING_CHECKED(UVaRest_BreakJson, Outputs) || PropertyName == GET_MEMBER_NAME_STRING_CHECKED(FVaRest_NamedType, Name) || PropertyName == GET_MEMBER_NAME_STRING_CHECKED(FVaRest_NamedType, Type) || @@ -254,7 +236,7 @@ FText UVaRest_BreakJson::GetMenuCategory() const if (CachedCategory.IsOutOfDate(this)) { // FText::Format() is slow, so we cache this to save on performance - CachedCategory.SetCachedText(FEditorCategoryUtils::BuildCategoryString(FCommonEditorCategory::Utilities, LOCTEXT("ActionMenuCategory", "Va Rest")), this); + CachedCategory.SetCachedText(FEditorCategoryUtils::BuildCategoryString(FCommonEditorCategory::Utilities, LOCTEXT("ActionMenuCategory", "VaRest")), this); } return CachedCategory; } @@ -262,18 +244,13 @@ FText UVaRest_BreakJson::GetMenuCategory() const void UVaRest_BreakJson::CreateProjectionPins(UEdGraphPin* Source) { const UEdGraphSchema_K2* K2Schema = GetDefault(); - UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRest.VaRestJsonObject'"))); + UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), nullptr, TEXT("class'VaRest.VaRestJsonObject'"))); for (TArray::TIterator it(Outputs); it; ++it) { -#if ENGINE_MINOR_VERSION >= 19 FName Type; -#else - FString Type; -#endif UObject* Subtype = nullptr; - FString FieldName = (*it).Name.ToString(); switch ((*it).Type) { @@ -297,7 +274,7 @@ void UVaRest_BreakJson::CreateProjectionPins(UEdGraphPin* Source) UEdGraphNode::FCreatePinParams OutputPinParams; OutputPinParams.ContainerType = (*it).bIsArray ? EPinContainerType::Array : EPinContainerType::None; - UEdGraphPin* OutputPin = CreatePin(EGPD_Output, Type, TEXT(""), Subtype, FName((*(*it).Name.ToString())), OutputPinParams); + UEdGraphPin* OutputPin = CreatePin(EGPD_Output, Type, TEXT(""), Subtype, (*it).Name, OutputPinParams); } } @@ -317,7 +294,7 @@ class FKCHandler_MakeJson : public FNodeHandlingFunctor virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) override { - UEdGraphPin* OutputPin = NULL; + UEdGraphPin* OutputPin = nullptr; for (int32 PinIndex = 0; PinIndex < Node->Pins.Num(); ++PinIndex) { @@ -329,16 +306,19 @@ class FKCHandler_MakeJson : public FNodeHandlingFunctor } } - UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRest.VaRestJsonObject'"))); + UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), nullptr, TEXT("class'VaRest.VaRestJsonObject'"))); FBPTerminal** TargetTerm = Context.NetMap.Find(OutputPin); if (TargetTerm == nullptr) { return; } + { - FName FunctionName = TEXT("ConstructVaRestJsonObject"); - UFunction* FunctionPtr = Class->FindFunctionByName(FunctionName); + UClass* SubsystemClass = Cast(StaticLoadObject(UClass::StaticClass(), nullptr, TEXT("class'VaRest.VaRestSubsystem'"))); + + const FName FunctionName = TEXT("StaticConstructVaRestJsonObject"); + UFunction* FunctionPtr = SubsystemClass->FindFunctionByName(FunctionName); FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node); Statement.Type = KCST_CallFunction; Statement.FunctionToCall = FunctionPtr; @@ -357,37 +337,22 @@ class FKCHandler_MakeJson : public FNodeHandlingFunctor UEdGraphPin* Pin = Node->Pins[PinIndex]; if (Pin && (EGPD_Input == Pin->Direction)) { - FBPTerminal** Source = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(Pin)); -#if ENGINE_MINOR_VERSION >= 19 const FName& FieldName = Pin->PinName; const FName& FieldType = Pin->PinType.PinCategory; -#else - const FString& FieldName = Pin->PinName; - const FString& FieldType = Pin->PinType.PinCategory; -#endif FBPTerminal* FieldNameTerm = Context.CreateLocalTerminal(ETerminalSpecification::TS_Literal); FieldNameTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_String; -#if ENGINE_MINOR_VERSION >= 13 FieldNameTerm->SourcePin = Pin; -#else - FieldNameTerm->Source = Pin; -#endif -#if ENGINE_MINOR_VERSION >= 19 FieldNameTerm->Name = FieldName.ToString(); FieldNameTerm->TextLiteral = FText::FromName(FieldName); -#else - FieldNameTerm->Name = FieldName; - FieldNameTerm->TextLiteral = FText::FromString(FieldName); -#endif FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node); FName FunctionName; - bool bIsArray = Pin->PinType.ContainerType == EPinContainerType::Array; + const bool bIsArray = Pin->PinType.ContainerType == EPinContainerType::Array; if (FieldType == CompilerContext.GetSchema()->PC_Boolean) { FunctionName = bIsArray ? TEXT("SetBoolArrayField") : TEXT("SetBoolField"); @@ -485,14 +450,10 @@ void UVaRest_MakeJson::AllocateDefaultPins() { const UEdGraphSchema_K2* K2Schema = GetDefault(); - UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRest.VaRestJsonObject'"))); + UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), nullptr, TEXT("class'VaRest.VaRestJsonObject'"))); UEdGraphPin* Pin = CreatePin(EGPD_Output, K2Schema->PC_Object, TEXT(""), Class, TEXT("Target")); -#if ENGINE_MINOR_VERSION >= 17 K2Schema->SetPinAutogeneratedDefaultValueBasedOnType(Pin); -#else - K2Schema->SetPinDefaultValueBasedOnType(Pin); -#endif CreateProjectionPins(Pin); } @@ -504,7 +465,7 @@ FLinearColor UVaRest_MakeJson::GetNodeTitleColor() const void UVaRest_MakeJson::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) { - FName PropertyName = (PropertyChangedEvent.Property != NULL) ? PropertyChangedEvent.Property->GetFName() : NAME_None; + const FName PropertyName = (PropertyChangedEvent.Property != nullptr) ? PropertyChangedEvent.Property->GetFName() : NAME_None; if (PropertyName == GET_MEMBER_NAME_STRING_CHECKED(UVaRest_MakeJson, Inputs) || PropertyName == GET_MEMBER_NAME_STRING_CHECKED(FVaRest_NamedType, Name) || PropertyName == GET_MEMBER_NAME_STRING_CHECKED(FVaRest_NamedType, Type) || @@ -545,7 +506,7 @@ FText UVaRest_MakeJson::GetMenuCategory() const if (CachedCategory.IsOutOfDate(this)) { // FText::Format() is slow, so we cache this to save on performance - CachedCategory.SetCachedText(FEditorCategoryUtils::BuildCategoryString(FCommonEditorCategory::Utilities, LOCTEXT("ActionMenuCategory", "Va Rest")), this); + CachedCategory.SetCachedText(FEditorCategoryUtils::BuildCategoryString(FCommonEditorCategory::Utilities, LOCTEXT("ActionMenuCategory", "VaRest")), this); } return CachedCategory; } @@ -553,13 +514,12 @@ FText UVaRest_MakeJson::GetMenuCategory() const void UVaRest_MakeJson::CreateProjectionPins(UEdGraphPin* Source) { const UEdGraphSchema_K2* K2Schema = GetDefault(); - UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), NULL, TEXT("class'VaRest.VaRestJsonObject'"))); + UClass* Class = Cast(StaticLoadObject(UClass::StaticClass(), nullptr, TEXT("class'VaRest.VaRestJsonObject'"))); for (TArray::TIterator it(Inputs); it; ++it) { FName Type; UObject* Subtype = nullptr; - FString FieldName = (*it).Name.ToString(); switch ((*it).Type) { @@ -583,13 +543,9 @@ void UVaRest_MakeJson::CreateProjectionPins(UEdGraphPin* Source) UEdGraphNode::FCreatePinParams InputPinParams; InputPinParams.ContainerType = (*it).bIsArray ? EPinContainerType::Array : EPinContainerType::None; - UEdGraphPin* InputPin = CreatePin(EGPD_Input, Type, TEXT(""), Subtype, FName((*(*it).Name.ToString())), InputPinParams); + UEdGraphPin* InputPin = CreatePin(EGPD_Input, Type, TEXT(""), Subtype, (*it).Name, InputPinParams); -#if ENGINE_MINOR_VERSION >= 20 InputPin->SetSavePinIfOrphaned(false); -#else - InputPin->bSavePinIfOrphaned = false; -#endif } } diff --git a/Source/VaRestEditor/Public/VaRestEditor.h b/Source/VaRestEditor/Public/VaRestEditor.h index a51c92c9..a5e0a8ae 100644 --- a/Source/VaRestEditor/Public/VaRestEditor.h +++ b/Source/VaRestEditor/Public/VaRestEditor.h @@ -2,7 +2,7 @@ #pragma once -#include "Modules/ModuleManager.h" +#include "Modules/ModuleInterface.h" class FVaRestEditorModule : public IModuleInterface { diff --git a/Source/VaRestEditor/Public/VaRest_BreakJson.h b/Source/VaRestEditor/Public/VaRest_BreakJson.h index dcdf51b5..dcf2195a 100644 --- a/Source/VaRestEditor/Public/VaRest_BreakJson.h +++ b/Source/VaRestEditor/Public/VaRest_BreakJson.h @@ -5,11 +5,7 @@ #include "Runtime/Launch/Resources/Version.h" -#if ENGINE_MINOR_VERSION >= 15 #include "CoreMinimal.h" -#else -#include "Engine.h" -#endif #include "K2Node.h" #include "VaRest_BreakJson.generated.h" @@ -27,10 +23,10 @@ enum class EVaRest_JsonType : uint8 USTRUCT(BlueprintType) struct FVaRest_NamedType { - GENERATED_USTRUCT_BODY(); + GENERATED_USTRUCT_BODY() UPROPERTY(EditAnywhere, Category = NamedType) - FText Name; + FName Name; UPROPERTY(EditAnywhere, Category = NamedType) EVaRest_JsonType Type; diff --git a/VaRest.uplugin b/VaRest.uplugin index 610331b5..c67a677b 100644 --- a/VaRest.uplugin +++ b/VaRest.uplugin @@ -2,11 +2,11 @@ "FileVersion" : 3, "FriendlyName" : "VaRest", - "Version" : 28, - "VersionName" : "1.1-r28", + "Version" : 33, + "VersionName" : "1.1.33", "CreatedBy" : "Vladimir Alyamkin", - "CreatedByURL" : "https://alyamkin.com", - "EngineVersion" : "4.24.0", + "CreatedByURL" : "https://ufna.dev", + "EngineVersion" : "4.27.0", "Description" : "Plugin that makes REST (JSON) server communication easy to use", "Category" : "Network", "DocsURL": "https://bit.ly/VaRest-Docs", @@ -24,4 +24,4 @@ "Type": "UncookedOnly" } ] -} \ No newline at end of file +}