halfcat73
(halfcat73)
November 25, 2023, 10:33am
1
Hi,
When the game exits, I need to send a HTTP request and to wait for its completion (with a timeout of a couple of seconds) before allowing the game to actually exit.
I could create the http request in the Shutdown method of a module / game instance and call Wait() on the OnProcessRequestComplete delegate of the HttpRequest.
But it would block the game main thread…
Is there a better solution?
3dRaven
(3dRaven)
November 25, 2023, 11:20am
2
Perhaps try the varest plugin. It has a latent request node which you can bind success and failure to events. (Apply URL is a latent function)
halfcat73
(halfcat73)
November 28, 2023, 9:47pm
3
@3dRaven
I forgot to mention that I need to make the http request in C++. VaRest seems to dedicated to blueprints.
Moreover, how could it help me to run an http request at game exit?
Thank you
3dRaven
(3dRaven)
November 28, 2023, 9:51pm
4
You would need to have the logic built in a way where the user triggers a quit game command => Game does http request => receives reply => calls quit game function.
If you are thinking of catching an ALT + F4 then it would be practically impossible.
The only way that could ever be done is if you had a parallel program that would ping the game and upon not receiving a reply do the request. (sort of like a watchdog in a microcontroller)
I’ll check the stock http requests in c++ and see if there is any async functions.
3dRaven
(3dRaven)
November 28, 2023, 11:11pm
5
header
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Interfaces/IHttpRequest.h"
#include "HTTPRequestActor.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FHttpRequestFinished, bool, Finished, FString, Message);
/**
*
*/
UCLASS(Blueprintable)
class QREQ_API AHTTPRequestActor : public AActor
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
void QuitRequest(FString UrlAddressAsString, FString OutputString);
void OnGetUsersResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
UPROPERTY(BlueprintAssignable)
FHttpRequestFinished RequestFinishedDelegate;
};
.CPP
// Fill out your copyright notice in the Description page of Project Settings.
#include "HTTPRequestActor.h"
#include "HttpModule.h"
#include "Kismet/GameplayStatics.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Interfaces/IHttpResponse.h"
void AHTTPRequestActor::QuitRequest(FString UrlAddressAsString, FString OutputString) {
TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
HttpRequest->SetVerb("POST");
HttpRequest->SetHeader("Content-Type", "application/json");
HttpRequest->SetURL(*FString::Printf(TEXT("%s"), *UrlAddressAsString));
HttpRequest->SetContentAsString(OutputString);
HttpRequest->OnProcessRequestComplete().BindUObject(this, &AHTTPRequestActor::OnGetUsersResponse);
HttpRequest->ProcessRequest();
}
void AHTTPRequestActor::OnGetUsersResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
if (bWasSuccessful)
{
TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject());
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(Response->GetContentAsString());
FJsonSerializer::Deserialize(JsonReader, JsonObject);
FString string_value_read = JsonObject->GetStringField("success");
if (string_value_read == "true") {
RequestFinishedDelegate.Broadcast(true, "Success");
bool IgnorePlatformRestrictions = true;
if (APlayerController* pc = UGameplayStatics::GetPlayerController(GetWorld(), 0)) {
UKismetSystemLibrary::QuitGame(GetWorld(), pc, EQuitPreference::Quit, IgnorePlatformRestrictions);
}
}
else {
RequestFinishedDelegate.Broadcast(false, "Key not found response: " + Response.Get()->GetContentAsString());
// Request failed
}
}
else {
FString Message = "Request failed [" + FString::FromInt(Response.Get()->GetResponseCode()) + "] " + Response.Get()->GetContentAsString();
RequestFinishedDelegate.Broadcast(false, Message);
}
}
You will need to modify
FString string_value_read = JsonObject->GetStringField("success");
if (string_value_read == "true") {
}
to the needed validation you want from the request response.
You can also bind to an exposed delegate RequestFinishedDelegate
and quit that way
(you would have to remove the hard-coded quit)
Example project:
QReq.zip (125.8 KB)
You may want to expose the quit condition as a pin. Not sure what you need so kept it simple.
Executed via QuitRequest