lyra_game_ue/Source/LyraGame/Tests/LyraGameplayRpcRegistrationComponent.cpp
Goran Lazarevski 3bcab085f8 Initial commit
2025-03-20 11:06:26 +01:00

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