230 lines
7.4 KiB
C++
230 lines
7.4 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "LyraGameplayRpcRegistrationComponent.h"
|
|
#include "Player/LyraPlayerController.h"
|
|
#include "Character/LyraPawn.h"
|
|
#include "Player/LyraPlayerState.h"
|
|
#include "Engine/GameViewportClient.h"
|
|
#include "Engine/GameInstance.h"
|
|
#include "Misc/CommandLine.h"
|
|
#include "EngineMinimal.h"
|
|
|
|
#include "Character/LyraHealthComponent.h"
|
|
#include "Inventory/LyraInventoryItemDefinition.h"
|
|
#include "Inventory/LyraInventoryItemInstance.h"
|
|
#include "Inventory/LyraInventoryManagerComponent.h"
|
|
#include "Character/LyraPawnExtensionComponent.h"
|
|
|
|
ULyraGameplayRpcRegistrationComponent* ULyraGameplayRpcRegistrationComponent::ObjectInstance = nullptr;
|
|
ULyraGameplayRpcRegistrationComponent* ULyraGameplayRpcRegistrationComponent::GetInstance()
|
|
{
|
|
#if WITH_RPC_REGISTRY
|
|
if (ObjectInstance == nullptr)
|
|
{
|
|
ObjectInstance = NewObject<ULyraGameplayRpcRegistrationComponent>();
|
|
FParse::Value(FCommandLine::Get(), TEXT("externalrpclistenaddress="), ObjectInstance->ListenerAddress);
|
|
FParse::Value(FCommandLine::Get(), TEXT("rpcsenderid="), ObjectInstance->SenderID);
|
|
if (!UExternalRpcRegistry::GetInstance())
|
|
{
|
|
GLog->Log(TEXT("BotRPC"), ELogVerbosity::Warning, FString::Printf(TEXT("Unable to create RPC Registry Instance. This might lead to issues using the RPC Registry.")));
|
|
}
|
|
ObjectInstance->AddToRoot();
|
|
}
|
|
#endif
|
|
return ObjectInstance;
|
|
}
|
|
|
|
UWorld* FindGameWorld()
|
|
{
|
|
//Find Game World
|
|
if (GEngine->GameViewport)
|
|
{
|
|
UGameInstance* GameInstance = GEngine->GameViewport->GetGameInstance();
|
|
return GameInstance ? GameInstance->GetWorld() : nullptr;
|
|
}
|
|
return GWorld;
|
|
}
|
|
|
|
ALyraPlayerController* GetPlayerController()
|
|
{
|
|
UWorld* LocalWorld = FindGameWorld();
|
|
if (!LocalWorld)
|
|
{
|
|
return nullptr;
|
|
}
|
|
//Find PlayerController
|
|
ALyraPlayerController* PlayerController = Cast<ALyraPlayerController>(LocalWorld->GetFirstPlayerController());
|
|
if (!PlayerController)
|
|
{
|
|
return nullptr;
|
|
}
|
|
else
|
|
{
|
|
return PlayerController;
|
|
}
|
|
}
|
|
|
|
#if WITH_RPC_REGISTRY
|
|
|
|
TSharedPtr<FJsonObject> ULyraGameplayRpcRegistrationComponent::GetJsonObjectFromRequestBody(TArray<uint8> InRequestBody)
|
|
{
|
|
FUTF8ToTCHAR WByteBuffer(reinterpret_cast<const ANSICHAR*>(InRequestBody.GetData()), InRequestBody.Num());
|
|
const FString IncomingRequestBody = FString::ConstructFromPtrSize(WByteBuffer.Get(), WByteBuffer.Length());
|
|
TSharedPtr<FJsonObject> BodyObject = MakeShareable(new FJsonObject());
|
|
TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(IncomingRequestBody);
|
|
|
|
if (FJsonSerializer::Deserialize(JsonReader, BodyObject) && BodyObject.IsValid())
|
|
{
|
|
return BodyObject;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
void ULyraGameplayRpcRegistrationComponent::RegisterAlwaysOnHttpCallbacks()
|
|
{
|
|
Super::RegisterAlwaysOnHttpCallbacks();
|
|
const FExternalRpcArgumentDesc CommandDesc(TEXT("command"), TEXT("string"), TEXT("The command to tell the executable to run."));
|
|
|
|
RegisterHttpCallback(FName(TEXT("CheatCommand")),
|
|
FHttpPath("/core/cheatcommand"),
|
|
EHttpServerRequestVerbs::VERB_POST,
|
|
FHttpRequestHandler::CreateUObject(this, &ThisClass::HttpExecuteCheatCommand),
|
|
true,
|
|
TEXT("Cheats"),
|
|
TEXT("raw"),
|
|
{ CommandDesc });
|
|
}
|
|
|
|
void ULyraGameplayRpcRegistrationComponent::RegisterInMatchHttpCallbacks()
|
|
{
|
|
RegisterHttpCallback(FName(TEXT("GetPlayerStatus")),
|
|
FHttpPath("/player/status"),
|
|
EHttpServerRequestVerbs::VERB_GET,
|
|
FHttpRequestHandler::CreateUObject(this, &ThisClass::HttpGetPlayerVitalsCommand),
|
|
true);
|
|
|
|
RegisterHttpCallback(FName(TEXT("PlayerFireOnce")),
|
|
FHttpPath("/player/status"),
|
|
EHttpServerRequestVerbs::VERB_POST,
|
|
FHttpRequestHandler::CreateUObject(this, &ThisClass::HttpFireOnceCommand),
|
|
true);
|
|
|
|
}
|
|
|
|
void ULyraGameplayRpcRegistrationComponent::RegisterFrontendHttpCallbacks()
|
|
{
|
|
// TODO: Add Matchmaking RPCs here
|
|
}
|
|
|
|
|
|
void ULyraGameplayRpcRegistrationComponent::DeregisterHttpCallbacks()
|
|
{
|
|
Super::DeregisterHttpCallbacks();
|
|
}
|
|
|
|
bool ULyraGameplayRpcRegistrationComponent::HttpExecuteCheatCommand(const FHttpServerRequest& Request, const FHttpResultCallback& OnComplete)
|
|
{
|
|
TSharedPtr<FJsonObject> BodyObject = GetJsonObjectFromRequestBody(Request.Body);
|
|
|
|
if (!BodyObject.IsValid())
|
|
{
|
|
TUniquePtr<FHttpServerResponse>Response = CreateSimpleResponse(false, TEXT("Invalid body object"));
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
if (BodyObject->GetStringField(TEXT("command")).IsEmpty())
|
|
{
|
|
TUniquePtr<FHttpServerResponse>Response = CreateSimpleResponse(false, TEXT("command not found in json body"));
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
ALyraPlayerController* LPC = GetPlayerController();
|
|
if (!LPC)
|
|
{
|
|
TUniquePtr<FHttpServerResponse>Response = CreateSimpleResponse(false, TEXT("player controller not found"));
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
FString CheatCommand = FString::Printf(TEXT("%s"), *BodyObject->GetStringField(TEXT("command")));
|
|
LPC->ConsoleCommand(*CheatCommand, true);
|
|
|
|
TUniquePtr<FHttpServerResponse>Response = CreateSimpleResponse(true);
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
|
|
bool ULyraGameplayRpcRegistrationComponent::HttpFireOnceCommand(const FHttpServerRequest& Request, const FHttpResultCallback& OnComplete)
|
|
{
|
|
ALyraPlayerController* LPC = GetPlayerController();
|
|
if (!LPC)
|
|
{
|
|
TUniquePtr<FHttpServerResponse> Response = CreateSimpleResponse(false, TEXT("No player controller found"));
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
APawn* FortPlayerPawn = LPC->GetPawn();
|
|
if (!FortPlayerPawn)
|
|
{
|
|
TUniquePtr<FHttpServerResponse> Response = CreateSimpleResponse(false, TEXT("Player pawn not found"));
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
|
|
// TODO: Fire Once here
|
|
TUniquePtr<FHttpServerResponse> Response = CreateSimpleResponse(true);
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
|
|
bool ULyraGameplayRpcRegistrationComponent::HttpGetPlayerVitalsCommand(const FHttpServerRequest& Request, const FHttpResultCallback& OnComplete)
|
|
{
|
|
ALyraPlayerController* LPC = GetPlayerController();
|
|
if (!LPC)
|
|
{
|
|
TUniquePtr<FHttpServerResponse> Response = CreateSimpleResponse(false, TEXT("No player controller found"));
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
APawn* PlayerPawn = LPC->GetPawn();
|
|
if (!PlayerPawn)
|
|
{
|
|
TUniquePtr<FHttpServerResponse> Response = CreateSimpleResponse(false, TEXT("Player pawn not found"));
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
|
|
ALyraPlayerState* LyraPlayerState = LPC->GetLyraPlayerState();
|
|
if (!LyraPlayerState)
|
|
{
|
|
TUniquePtr<FHttpServerResponse> Response = CreateSimpleResponse(false, TEXT("Player state not found"));
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
|
|
FString ResponseStr;
|
|
TSharedRef<TJsonWriter<>> JsonWriter = TJsonWriterFactory<>::Create(&ResponseStr);
|
|
TSharedPtr<FJsonObject> BodyObject = MakeShareable(new FJsonObject());
|
|
JsonWriter->WriteObjectStart();
|
|
if (ULyraHealthComponent* HealthComponent = ULyraHealthComponent::FindHealthComponent(PlayerPawn))
|
|
{
|
|
JsonWriter->WriteValue(TEXT("health"), FString::SanitizeFloat(HealthComponent->GetHealth()));
|
|
}
|
|
if (ULyraInventoryManagerComponent* InventoryComponent = LPC->GetComponentByClass<ULyraInventoryManagerComponent>())
|
|
{
|
|
JsonWriter->WriteArrayStart(TEXT("inventory"));
|
|
for (ULyraInventoryItemInstance* ItemInstance : InventoryComponent->GetAllItems())
|
|
{
|
|
// TODO: Dump any relevant player info here.
|
|
}
|
|
JsonWriter->WriteArrayEnd();
|
|
}
|
|
JsonWriter->WriteObjectEnd();
|
|
JsonWriter->Close();
|
|
TUniquePtr<FHttpServerResponse>Response = FHttpServerResponse::Create(ResponseStr, TEXT("application/json"));
|
|
OnComplete(MoveTemp(Response));
|
|
return true;
|
|
}
|
|
|
|
#endif |