2025-06-29 19:04:36 +02:00
|
|
|
|
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
|
|
|
|
|
|
#include "Subsystems/DTFluxNetworkSubsystem.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "DTFluxCoreModule.h"
|
|
|
|
|
|
#include "DTFluxNetworkModule.h"
|
|
|
|
|
|
#include "DTFluxNetworkSettings.h"
|
2025-07-08 16:50:31 +02:00
|
|
|
|
#include "DTFluxQueuedManager.h"
|
|
|
|
|
|
#include "DTFluxQueuedManager.h"
|
2025-06-29 19:04:36 +02:00
|
|
|
|
#include "JsonObjectConverter.h"
|
|
|
|
|
|
#include "Clients/DTFluxHttpClient.h"
|
|
|
|
|
|
#include "Clients/DTFluxWebSocketClient.h"
|
|
|
|
|
|
#include "Struct/DTFluxServerResponseStruct.h"
|
|
|
|
|
|
#include "Struct/DTFluxRequestStructs.h"
|
|
|
|
|
|
#include "Struct/DTFluxRaceDataServerResponse.h"
|
2025-06-30 19:02:19 +02:00
|
|
|
|
#include "Struct/DTFluxRankingServerResponse.h"
|
2025-07-03 17:28:51 +02:00
|
|
|
|
#include "Struct/DTFluxSplitSensorServerResponse.h"
|
2025-06-29 19:04:36 +02:00
|
|
|
|
#include "Struct/DTFluxTeamListServerResponse.h"
|
2025-07-03 17:28:51 +02:00
|
|
|
|
#include "Types/Objects/UDTFluxParticipantFactory.h"
|
2025-06-29 19:04:36 +02:00
|
|
|
|
#include "Types/Struct/DTFluxRaceDataStructs.h"
|
2025-07-03 17:28:51 +02:00
|
|
|
|
#include "Types/Struct/DTFluxSplitSensor.h"
|
2025-06-29 19:04:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// === CONNEXION WEBSOCKET ===
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::Connect()
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
WsClient->SetAddress(ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port));
|
|
|
|
|
|
WsClient->Connect();
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UDTFluxNetworkSubsystem::Disconnect()
|
|
|
|
|
|
{
|
|
|
|
|
|
WsClient->Disconnect();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UDTFluxNetworkSubsystem::Reconnect()
|
|
|
|
|
|
{
|
|
|
|
|
|
ReconnectWs(FName("Ws_Client_0"));
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// === REQUÊTES AVEC TRACKING ===
|
|
|
|
|
|
|
|
|
|
|
|
FGuid UDTFluxNetworkSubsystem::SendTrackedRequest(
|
|
|
|
|
|
EDTFluxApiDataType RequestType,
|
|
|
|
|
|
int32 ContestId,
|
|
|
|
|
|
int32 StageId,
|
|
|
|
|
|
int32 SplitId,
|
|
|
|
|
|
float TimeoutSeconds)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!QueueManager)
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("QueueManager is not initialized"));
|
|
|
|
|
|
return FGuid();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Vérifier si une requête similaire est déjà en cours (optionnel)
|
|
|
|
|
|
if (IsRequestPending(RequestType, ContestId, StageId, SplitId))
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning,
|
|
|
|
|
|
TEXT("Similar request already pending: Type=%d, Contest=%d, Stage=%d, Split=%d"),
|
|
|
|
|
|
(int32)RequestType, ContestId, StageId, SplitId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Créer et enqueue la requête
|
|
|
|
|
|
FGuid RequestId = QueueManager->QueueRequest(RequestType, ContestId, StageId, SplitId);
|
|
|
|
|
|
|
|
|
|
|
|
// Envoyer immédiatement si possible (le QueueManager gère la queue)
|
|
|
|
|
|
if (const FDTFluxQueuedRequest* QueuedRequest = QueueManager->GetRequest(RequestId))
|
|
|
|
|
|
{
|
|
|
|
|
|
SendQueuedRequest(*QueuedRequest);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Log, TEXT("Queued tracked request %s: Type=%d, Contest=%d, Stage=%d, Split=%d"),
|
|
|
|
|
|
*RequestId.ToString(), (int32)RequestType, ContestId, StageId, SplitId);
|
|
|
|
|
|
|
|
|
|
|
|
return RequestId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FGuid UDTFluxNetworkSubsystem::SendTrackedRequestWithCallback(
|
|
|
|
|
|
EDTFluxApiDataType RequestType,
|
|
|
|
|
|
int32 ContestId,
|
|
|
|
|
|
int32 StageId,
|
|
|
|
|
|
int32 SplitId,
|
|
|
|
|
|
FOnDTFluxRequestResponse OnCompleted,
|
|
|
|
|
|
FOnDTFluxRequestTimeout OnTimeout,
|
|
|
|
|
|
float TimeoutSeconds)
|
|
|
|
|
|
{
|
|
|
|
|
|
FGuid RequestId = SendTrackedRequest(RequestType, ContestId, StageId, SplitId, TimeoutSeconds);
|
|
|
|
|
|
|
|
|
|
|
|
if (RequestId.IsValid())
|
|
|
|
|
|
{
|
|
|
|
|
|
// Stocker les callbacks pour cette requête
|
|
|
|
|
|
if (OnCompleted.IsBound())
|
|
|
|
|
|
{
|
|
|
|
|
|
PendingCallbacks.Add(RequestId, OnCompleted);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (OnTimeout.IsBound())
|
|
|
|
|
|
{
|
|
|
|
|
|
PendingTimeoutCallbacks.Add(RequestId, OnTimeout);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return RequestId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool UDTFluxNetworkSubsystem::GetTrackedRequest(const FGuid& RequestId, FDTFluxQueuedRequest& OutRequest) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!QueueManager)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FDTFluxQueuedRequest* Request = QueueManager->GetRequest(RequestId);
|
|
|
|
|
|
if (Request)
|
|
|
|
|
|
{
|
|
|
|
|
|
OutRequest = *Request;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const FDTFluxQueuedRequest* UDTFluxNetworkSubsystem::GetTrackedRequestPtr(const FGuid& RequestId) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!QueueManager)
|
|
|
|
|
|
{
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
return QueueManager->GetRequest(RequestId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool UDTFluxNetworkSubsystem::HasRequestReceivedResponse(const FGuid& RequestId) const
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxQueuedRequest Request;
|
|
|
|
|
|
if (GetTrackedRequest(RequestId, Request))
|
|
|
|
|
|
{
|
|
|
|
|
|
return Request.bHasReceivedResponse;
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
FString UDTFluxNetworkSubsystem::GetRequestResponseData(const FGuid& RequestId) const
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxQueuedRequest Request;
|
|
|
|
|
|
if (GetTrackedRequest(RequestId, Request))
|
|
|
|
|
|
{
|
|
|
|
|
|
return Request.RawResponse;
|
|
|
|
|
|
}
|
|
|
|
|
|
return FString();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool UDTFluxNetworkSubsystem::IsRequestPending(EDTFluxRequestType RequestType, int32 ContestId, int32 StageId,
|
|
|
|
|
|
int32 SplitId) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!QueueManager)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return QueueManager->IsRequestPending(RequestType, ContestId, StageId, SplitId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int32 UDTFluxNetworkSubsystem::GetPendingRequestCount() const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!QueueManager)
|
|
|
|
|
|
{
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
return QueueManager->GetPendingRequestCount();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UDTFluxQueuedManager* UDTFluxNetworkSubsystem::GetQueueManager() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return QueueManager;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType, int InContestId, int InStageId,
|
|
|
|
|
|
int InSplitId)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
FString Message;
|
|
|
|
|
|
switch (RequestType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case EDTFluxRequestType::ContestRanking:
|
|
|
|
|
|
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxContestRankingRequest(InContestId), Message);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case EDTFluxRequestType::StageRanking:
|
|
|
|
|
|
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxStageRankingRequest(InContestId, InStageId), Message);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case EDTFluxRequestType::SplitRanking:
|
2025-07-08 16:50:31 +02:00
|
|
|
|
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxSplitRankingRequest(InContestId, InStageId, InSplitId),
|
|
|
|
|
|
Message);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
break;
|
|
|
|
|
|
case EDTFluxRequestType::TeamList:
|
|
|
|
|
|
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxTeamListRequest(), Message);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case EDTFluxRequestType::RaceData:
|
|
|
|
|
|
FJsonObjectConverter::UStructToJsonObjectString(FDTFluxRaceDataRequest(), Message);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
//Dirty trick to fix Case
|
2025-07-08 16:50:31 +02:00
|
|
|
|
Message = Message.Replace(TEXT("Id"),TEXT("ID"), ESearchCase::CaseSensitive);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
UE_LOG(logDTFluxCore, Warning, TEXT("Sending Request %s"), *Message);
|
|
|
|
|
|
SendMessage(Message);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::SendMessage(const FString& Message)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-03 17:28:51 +02:00
|
|
|
|
UE_LOG(logDTFluxCore, Warning, TEXT("Sending Message %s"), *Message);
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (WsClient.IsValid() && WsClient->CanSend())
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
|
|
|
|
|
WsClient->Send(Message);
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Log, TEXT("Can send request"));
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("[Websocket Not Connected]. Connect before sending requests..."));
|
|
|
|
|
|
}
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::Initialize(FSubsystemCollectionBase& Collection)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
Super::Initialize(Collection);
|
|
|
|
|
|
FDTFluxCoreModule& DTFluxCore = FModuleManager::Get().LoadModuleChecked<FDTFluxCoreModule>("DTFluxCore");
|
2025-07-08 16:50:31 +02:00
|
|
|
|
|
2025-06-29 19:04:36 +02:00
|
|
|
|
UDTFluxNetworkSettings* NetworkSettings = GetMutableDefault<UDTFluxNetworkSettings>();
|
|
|
|
|
|
UDTFluxNetworkSettings::GetWebSocketSettings(NetworkSettings, WsSettings);
|
|
|
|
|
|
UDTFluxNetworkSettings::GetHTTPSettings(NetworkSettings, HttpSettings);
|
|
|
|
|
|
WsClient = MakeShareable<FDTFluxWebSocketClient>(new FDTFluxWebSocketClient());
|
|
|
|
|
|
HttpClient = MakeShareable<FDTFluxHttpClient>(new FDTFluxHttpClient());
|
|
|
|
|
|
RegisterWebSocketEvents();
|
|
|
|
|
|
RegisterHttpEvents();
|
|
|
|
|
|
#if WITH_EDITOR
|
|
|
|
|
|
NetworkSettings->OnDTFluxWebSocketSettingsChanged.AddUFunction(this, FName("WsSettingsChanged"));
|
|
|
|
|
|
NetworkSettings->OnDTFluxHttpSettingsChanged.AddUFunction(this, FName("HttpSettingsChanged"));
|
|
|
|
|
|
#endif
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (WsSettings.bShouldConnectAtStartup)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
WsClient->SetAddress(ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port));
|
|
|
|
|
|
WsClient->Connect();
|
|
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
|
|
|
|
|
|
// Initialisation du Queue Manager
|
|
|
|
|
|
QueueManager = NewObject<UDTFluxQueuedManager>(this);
|
|
|
|
|
|
QueueManager->Initialize();
|
|
|
|
|
|
|
|
|
|
|
|
// Connexion au delegate de timeout du Queue Manager
|
|
|
|
|
|
QueueManager->OnRequestTimedOut.AddDynamic(this, &UDTFluxNetworkSubsystem::OnRequestTimedOut_Internal);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::Deinitialize()
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
Super::Deinitialize();
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// Nettoyer le Queue Manager
|
|
|
|
|
|
if (QueueManager)
|
|
|
|
|
|
{
|
|
|
|
|
|
QueueManager->OnRequestTimedOut.RemoveDynamic(this, &UDTFluxNetworkSubsystem::OnRequestTimedOut_Internal);
|
|
|
|
|
|
QueueManager->ClearAllRequests();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Nettoyer les callbacks
|
|
|
|
|
|
PendingCallbacks.Empty();
|
|
|
|
|
|
PendingTimeoutCallbacks.Empty();
|
|
|
|
|
|
// Déconnexion des clients
|
|
|
|
|
|
UnregisterWebSocketEvents();
|
|
|
|
|
|
UnregisterHttpEvents();
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::WsSettingsChanged(const FDTFluxWsSettings& NewWsSettings)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
// TODO Implement a ClientSelector To retrieve impacted WsClients and populate changes or maybe create a delegate
|
|
|
|
|
|
bool bNeedsReload = WsSettings != NewWsSettings;
|
|
|
|
|
|
|
|
|
|
|
|
WsSettings = NewWsSettings;
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (bNeedsReload || WsSettings.bShouldConnectAtStartup)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("WSocket Settings needs Reloding client"))
|
|
|
|
|
|
ReconnectWs(FName("Ws_Client_0"));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::HttpSettingsChanged(const FDTFluxHttpSettings& NewHttpSettings)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
// TODO Implement a ClientSelector To retrieve impacted HttpClients and populate changes or maybe create a delegate
|
|
|
|
|
|
HttpSettings = NewHttpSettings;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::ReconnectWs(const FName WsClientId)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
FString NewAddress = ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port);
|
|
|
|
|
|
WsClient->SetAddress(NewAddress);
|
|
|
|
|
|
WsClient->Reconnect();
|
|
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::ReconnectHttp(const FName WsClientId)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::RegisterWebSocketEvents()
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
OnWsConnectedEventDelegateHandle =
|
2025-07-03 17:28:51 +02:00
|
|
|
|
WsClient->RegisterConnectedEvent().AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
OnWsConnectionErrorEventDelegateHandle =
|
|
|
|
|
|
WsClient->RegisterConnectionError()
|
2025-07-08 16:50:31 +02:00
|
|
|
|
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem);
|
|
|
|
|
|
OnWsClosedEventDelegateHandle =
|
2025-06-29 19:04:36 +02:00
|
|
|
|
WsClient->RegisterClosedEvent()
|
2025-07-08 16:50:31 +02:00
|
|
|
|
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
OnWsMessageEventDelegateHandle =
|
|
|
|
|
|
WsClient->RegisterMessageEvent()
|
2025-07-08 16:50:31 +02:00
|
|
|
|
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
OnWsMessageSentEventDelegateHandle =
|
2025-07-08 16:50:31 +02:00
|
|
|
|
WsClient->RegisterMessageSentEvent()
|
|
|
|
|
|
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::RegisterHttpEvents()
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::UnregisterWebSocketEvents()
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (OnWsConnectedEventDelegateHandle.IsValid())
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
WsClient->UnregisterConnectedEvent().Remove(OnWsConnectedEventDelegateHandle);
|
|
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (OnWsConnectionErrorEventDelegateHandle.IsValid())
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
WsClient->UnregisterConnectionError().Remove(OnWsConnectionErrorEventDelegateHandle);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (OnWsClosedEventDelegateHandle.IsValid())
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
WsClient->UnregisterClosedEvent().Remove(OnWsClosedEventDelegateHandle);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (OnWsMessageEventDelegateHandle.IsValid())
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
WsClient->UnregisterMessageEvent().Remove(OnWsMessageEventDelegateHandle);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (OnWsMessageSentEventDelegateHandle.IsValid())
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
WsClient->UnregisterRawMessageEvent().Remove(OnWsMessageSentEventDelegateHandle);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::UnregisterHttpEvents()
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem()
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-03 17:28:51 +02:00
|
|
|
|
WsStatus = EDTFluxConnectionStatus::Connected;
|
2025-06-29 19:04:36 +02:00
|
|
|
|
OnWebSocketConnected.Broadcast();
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Is Connected with %s"), *WsClient->GetAddress())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem(const FString& Error)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Error with %s : %s"), *WsClient->GetAddress(), *Error);
|
2025-07-03 17:28:51 +02:00
|
|
|
|
WsStatus = EDTFluxConnectionStatus::Error;
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (WsSettings.bShouldAutoReconnectOnError)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
WsClient->Reconnect();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem(int32 StatusCode, const FString& Reason, bool bWasClean)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Error with %s :\n Reason : %s \tStatusCode : %i, bWasClean : %s"),
|
2025-07-08 16:50:31 +02:00
|
|
|
|
*WsClient->GetAddress(), *Reason, StatusCode, bWasClean ? TEXT("True") : TEXT("False"));
|
2025-07-03 17:28:51 +02:00
|
|
|
|
WsStatus = EDTFluxConnectionStatus::Closed;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::ParseTeamListResponse(FDTFluxServerResponse& Response)
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxTeamListDefinition TeamListDefinition;
|
|
|
|
|
|
Response.ParseTeamListResponse(TeamListDefinition);
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Parsing Team List Response"));
|
|
|
|
|
|
if (Response.GetParsingStatus() != EDTFluxResponseStatus::Success)
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseTeamListResponse() for JSON Response : %s"), *Response.RawMessage);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("PArsing OK. Sending to Core..."));
|
|
|
|
|
|
const bool bIsSuccessfullyBounded = OnTeamListReceived.ExecuteIfBound(TeamListDefinition);
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Inserting %i Participants [%s]"), TeamListDefinition.Participants.Num(),
|
|
|
|
|
|
bIsSuccessfullyBounded ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UDTFluxNetworkSubsystem::ParseRaceData(FDTFluxServerResponse& Response)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
FDTFluxRaceData RaceData;
|
|
|
|
|
|
Response.ParseRaceData(RaceData);
|
|
|
|
|
|
if (Response.GetParsingStatus() != EDTFluxResponseStatus::Success)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseRaceData() for JSON Response : %s"), *Response.RawMessage);
|
2025-07-03 17:28:51 +02:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
const bool bIsSuccessfullyBounded = OnRaceDataReceived.ExecuteIfBound(RaceData);
|
|
|
|
|
|
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Sending %i Contests, [%s]"), RaceData.Datas.Num(),
|
|
|
|
|
|
bIsSuccessfullyBounded ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UDTFluxNetworkSubsystem::ParseContestRanking(FDTFluxServerResponse& Response)
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxContestRankings ContestRankings;
|
|
|
|
|
|
Response.ParseContestRanking(ContestRankings);
|
|
|
|
|
|
if (Response.GetParsingStatus() != EDTFluxResponseStatus::Success)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseContestRanking() for JSON Response : %s"), *Response.RawMessage);
|
2025-07-03 17:28:51 +02:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
const bool bIsSuccessfullyBounded = OnContestRankingReceived.ExecuteIfBound(ContestRankings);
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws ContestRanking Data Sent for Contest %i, [%s]"),
|
|
|
|
|
|
ContestRankings.ContestId,
|
|
|
|
|
|
bIsSuccessfullyBounded ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UDTFluxNetworkSubsystem::ParseStageRankingResponse(FDTFluxServerResponse& Response)
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxStageRankings StageRankings;
|
|
|
|
|
|
Response.ParseStageRankingResponse(StageRankings);
|
|
|
|
|
|
if (Response.GetParsingStatus() != EDTFluxResponseStatus::Success)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseStageRankingResponse() for JSON Response : %s"),
|
|
|
|
|
|
*Response.RawMessage);
|
|
|
|
|
|
}
|
|
|
|
|
|
const bool bIsSuccessfullyBounded = OnStageRankingReceived.ExecuteIfBound(StageRankings);
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("StageRanking Data Sent for Contest %i, Stage %i\n[Result] : %s"),
|
|
|
|
|
|
StageRankings.ContestId, StageRankings.StageId,
|
|
|
|
|
|
bIsSuccessfullyBounded ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
|
|
|
|
|
|
}
|
2025-07-03 17:28:51 +02:00
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::ParseSplitRankingResponse(FDTFluxServerResponse& Response)
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxSplitRankings SplitRankings;
|
|
|
|
|
|
Response.ParseSplitRankingResponse(SplitRankings);
|
|
|
|
|
|
if (Response.GetParsingStatus() != EDTFluxResponseStatus::Success)
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseSplitRankingResponse() for JSON Response : %s"),
|
|
|
|
|
|
*Response.RawMessage);
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
const bool bIsSuccessfullyBounded = OnSplitRankingReceived.ExecuteIfBound(SplitRankings);
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("SplitRanking Data Sent for Contest %i, Stage %i, Split %i\n[Result] : %s"),
|
|
|
|
|
|
SplitRankings.ContestId, SplitRankings.StageId, SplitRankings.SplitId,
|
|
|
|
|
|
bIsSuccessfullyBounded ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
|
|
|
|
|
|
}
|
2025-07-03 17:28:51 +02:00
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::ParseStatusUpdateResponse(FDTFluxServerResponse& Response)
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxTeamStatusUpdate StatusUpdate;
|
|
|
|
|
|
Response.ParseStatusUpdateResponse(StatusUpdate);
|
|
|
|
|
|
if (Response.GetParsingStatus() != EDTFluxResponseStatus::Success)
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseStatusUpdateResponse() for JSON Response : %s"),
|
|
|
|
|
|
*Response.RawMessage);
|
|
|
|
|
|
}
|
|
|
|
|
|
const bool bIsSuccessfullyBounded = OnTeamStatusUpdateReceived.ExecuteIfBound(StatusUpdate);
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("StatusUpdate Data Sent for Bib %i with new status %s\n[Result] : %s"),
|
|
|
|
|
|
StatusUpdate.Bib, *UEnum::GetValueAsString(StatusUpdate.Status),
|
|
|
|
|
|
bIsSuccessfullyBounded ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::ParseSplitSensorResponse(FDTFluxServerResponse& Response)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
TArray<FDTFluxSplitSensorInfo> SplitSensorInfos = TArray<FDTFluxSplitSensorInfo>();
|
|
|
|
|
|
Response.ParseSplitSensorResponse(SplitSensorInfos);
|
|
|
|
|
|
if (Response.GetParsingStatus() != EDTFluxResponseStatus::Success)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseSplitSensorResponse() for JSON Response : %s"),
|
|
|
|
|
|
*Response.RawMessage);
|
|
|
|
|
|
}
|
|
|
|
|
|
for (auto& SplitSensorInfo : SplitSensorInfos)
|
|
|
|
|
|
{
|
|
|
|
|
|
const bool bIsSuccessfullyBounded = OnSplitSensorReceived.ExecuteIfBound(SplitSensorInfo);
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning,
|
|
|
|
|
|
TEXT("SplitSensor Data Sent for Bib %i on [Split %i] of [Stage %i] in [Contest %i]\n[Result] : %s"),
|
|
|
|
|
|
SplitSensorInfo.Bib, SplitSensorInfo.SplitId, SplitSensorInfo.StageId, SplitSensorInfo.ContestId,
|
|
|
|
|
|
bIsSuccessfullyBounded ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
EDTFluxResponseStatus UDTFluxNetworkSubsystem::ProcessPushMessage(FDTFluxServerResponse& Response)
|
|
|
|
|
|
{
|
|
|
|
|
|
EDTFluxResponseStatus ResponseStatus = EDTFluxResponseStatus::UnknownError;
|
|
|
|
|
|
if (DTFluxDataTypeUtils::IsPushOnly(Response.GetResponseType()))
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (Response.GetResponseType())
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
case EDTFluxApiDataType::SplitSensor:
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
TArray<FDTFluxSplitSensorInfo> SplitSensorInfos;
|
|
|
|
|
|
if (Response.ParseSplitSensorResponse(SplitSensorInfos))
|
|
|
|
|
|
{
|
|
|
|
|
|
for (const auto& SplitSensorInfo : SplitSensorInfos)
|
|
|
|
|
|
{
|
|
|
|
|
|
OnSplitSensorReceived.ExecuteIfBound(SplitSensorInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
ResponseStatus = Response.GetParsingStatus();
|
|
|
|
|
|
break;
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
case EDTFluxApiDataType::StatusUpdate:
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
FDTFluxTeamStatusUpdate StatusUpdate;
|
|
|
|
|
|
if (Response.ParseStatusUpdateResponse(StatusUpdate))
|
|
|
|
|
|
{
|
|
|
|
|
|
OnTeamStatusUpdateReceived.ExecuteIfBound(StatusUpdate);
|
|
|
|
|
|
}
|
|
|
|
|
|
ResponseStatus = Response.GetParsingStatus();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case EDTFluxApiDataType::TeamUpdate:
|
|
|
|
|
|
{
|
|
|
|
|
|
FDTFluxTeamListDefinition TeamUpdateList;
|
|
|
|
|
|
if (Response.ParseTeamUpdateResponse(TeamUpdateList))
|
|
|
|
|
|
{
|
|
|
|
|
|
OnTeamUpdateReceived.ExecuteIfBound(TeamUpdateList);
|
|
|
|
|
|
}
|
|
|
|
|
|
ResponseStatus = Response.GetParsingStatus();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
default:
|
|
|
|
|
|
{
|
|
|
|
|
|
ResponseStatus = EDTFluxResponseStatus::UnknownError;
|
|
|
|
|
|
break;
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
return ResponseStatus;
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::Parse(FDTFluxServerResponse& Response)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
EDTFluxResponseStatus ResponseStatus = EDTFluxResponseStatus::Success;
|
|
|
|
|
|
switch (Response.GetResponseType())
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
case EDTFluxApiDataType::RaceData:
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Legacy Parsing RaceData"));
|
|
|
|
|
|
ParseRaceData(Response);
|
|
|
|
|
|
ResponseStatus = Response.GetParsingStatus();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case EDTFluxApiDataType::TeamList:
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Legacy Parsing TeamList"));
|
|
|
|
|
|
ParseTeamListResponse(Response);
|
|
|
|
|
|
ResponseStatus = Response.GetParsingStatus();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case EDTFluxApiDataType::ContestRanking:
|
|
|
|
|
|
{
|
|
|
|
|
|
ParseContestRanking(Response);
|
|
|
|
|
|
ResponseStatus = Response.GetParsingStatus();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case EDTFluxApiDataType::StageRanking:
|
|
|
|
|
|
{
|
|
|
|
|
|
ParseStageRankingResponse(Response);
|
|
|
|
|
|
ResponseStatus = Response.GetParsingStatus();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case EDTFluxApiDataType::SplitRanking:
|
|
|
|
|
|
{
|
|
|
|
|
|
ParseSplitRankingResponse(Response);
|
|
|
|
|
|
ResponseStatus = Response.GetParsingStatus();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
default:
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("Legacy Parsing Unknown"));
|
|
|
|
|
|
ResponseStatus = EDTFluxResponseStatus::UnknownError;
|
|
|
|
|
|
break;
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (ResponseStatus != EDTFluxResponseStatus::Success)
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("UDTFluxNetworkSubsystem::Parse() Parsing failed"));
|
|
|
|
|
|
}
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
|
|
|
|
|
|
//TODO reforge API to keep track of Requests
|
|
|
|
|
|
void UDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString& MessageString)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// UE_LOG(logDTFluxNetwork, Warning, TEXT("Client %s :\nMessage Received : %s"), *WsClient->GetAddress(), *MessageString);
|
|
|
|
|
|
//Do Something With the message
|
|
|
|
|
|
EDTFluxResponseStatus ResponseStatus;
|
|
|
|
|
|
FDTFluxServerResponse Response(MessageString, ResponseStatus);
|
|
|
|
|
|
if (!TryMatchResponseToQueuedRequest(Response))
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Response %s does not match any queued request"),
|
|
|
|
|
|
*UEnum::GetValueAsString(Response.GetResponseType()));
|
|
|
|
|
|
if (ProcessPushMessage(Response) != EDTFluxResponseStatus::Success)
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Not a push message"));
|
|
|
|
|
|
// Legacy
|
|
|
|
|
|
Parse(Response);
|
|
|
|
|
|
}
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent)
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws %s :\nMessage Sent: %s"), *WsClient->GetAddress(), *MessageSent);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UDTFluxNetworkSubsystem::OnRequestTimedOut_Internal(const FDTFluxQueuedRequest& TimedOutRequest)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
UE_LOG(logDTFluxNetwork, Warning, TEXT("Request %s timed out: Type=%d, Contest=%d, Stage=%d, Split=%d"),
|
|
|
|
|
|
*TimedOutRequest.RequestId.ToString(),
|
|
|
|
|
|
(int32)TimedOutRequest.RequestType,
|
|
|
|
|
|
TimedOutRequest.ContestId,
|
|
|
|
|
|
TimedOutRequest.StageId,
|
|
|
|
|
|
TimedOutRequest.SplitId);
|
|
|
|
|
|
|
|
|
|
|
|
// Appeler le callback de timeout si présent
|
|
|
|
|
|
if (FOnDTFluxRequestTimeout* TimeoutCallback = PendingTimeoutCallbacks.Find(TimedOutRequest.RequestId))
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (TimeoutCallback->IsBound())
|
|
|
|
|
|
{
|
|
|
|
|
|
TimeoutCallback->Execute(TimedOutRequest.RequestId, TEXT("Request timeout"));
|
|
|
|
|
|
}
|
|
|
|
|
|
PendingTimeoutCallbacks.Remove(TimedOutRequest.RequestId);
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// Nettoyer les callbacks de succès aussi
|
|
|
|
|
|
PendingCallbacks.Remove(TimedOutRequest.RequestId);
|
|
|
|
|
|
|
|
|
|
|
|
// Broadcaster l'événement Blueprint
|
|
|
|
|
|
OnTrackedRequestFailed.Broadcast(TimedOutRequest.RequestId, TimedOutRequest.RequestType, TEXT("Request timeout"));
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
bool UDTFluxNetworkSubsystem::TryMatchResponseToQueuedRequest(const FDTFluxServerResponse& Response)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (!QueueManager)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
// Essayer de trouver une requête correspondante
|
|
|
|
|
|
// Note: Cette méthode nécessiterait une modification de UDTFluxQueuedManager pour supporter le matching par type et paramètres
|
|
|
|
|
|
|
|
|
|
|
|
// Pour l'instant, on utilise une approche simple : chercher la première requête du bon type
|
|
|
|
|
|
// Vous devrez probablement modifier UDTFluxQueuedManager pour ajouter une méthode comme FindMatchingRequest()
|
2025-07-03 17:28:51 +02:00
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
|
|
|
|
|
|
// Implémentation temporaire : on assume qu'il n'y a qu'une requête de chaque type en cours
|
|
|
|
|
|
if (QueueManager->IsRequestPending(Response.GetResponseType(), Response.ContestID, Response.StageID,
|
|
|
|
|
|
Response.SplitID))
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// Marquer comme répondu - vous devrez adapter cette méthode selon votre logique de matching
|
|
|
|
|
|
// Pour l'instant, on va faire un workaround simple
|
|
|
|
|
|
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Log,
|
|
|
|
|
|
TEXT("Matched response to queued request: Type=%s, Contest=%d, Stage=%d, Split=%d"),
|
|
|
|
|
|
*UEnum::GetValueAsString(Response.GetResponseType()), Response.ContestID, Response.StageID,
|
|
|
|
|
|
Response.SplitID);
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
|
|
|
|
|
|
return false;
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::CompleteTrackedRequest(const FGuid& RequestId, const FString& ResponseData,
|
|
|
|
|
|
EDTFluxRequestType RequestType)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// Marquer la requête comme ayant reçu une réponse
|
|
|
|
|
|
if (QueueManager)
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
QueueManager->MarkRequestAsResponded(RequestId);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Appeler le callback de succès si présent
|
|
|
|
|
|
if (FOnDTFluxRequestResponse* SuccessCallback = PendingCallbacks.Find(RequestId))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (SuccessCallback->IsBound())
|
2025-07-03 17:28:51 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
SuccessCallback->Execute(RequestId, ResponseData);
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
PendingCallbacks.Remove(RequestId);
|
2025-07-03 17:28:51 +02:00
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
|
|
|
|
|
|
// Nettoyer le callback de timeout
|
|
|
|
|
|
PendingTimeoutCallbacks.Remove(RequestId);
|
|
|
|
|
|
|
|
|
|
|
|
// Broadcaster l'événement Blueprint
|
|
|
|
|
|
OnTrackedRequestCompleted.Broadcast(RequestId, RequestType, ResponseData);
|
|
|
|
|
|
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Log, TEXT("Completed tracked request %s"), *RequestId.ToString());
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::FailTrackedRequest(const FGuid& RequestId, const FString& ErrorMessage,
|
|
|
|
|
|
EDTFluxRequestType RequestType)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// Appeler le callback d'erreur si présent
|
|
|
|
|
|
if (FOnDTFluxRequestTimeout* ErrorCallback = PendingTimeoutCallbacks.Find(RequestId))
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (ErrorCallback->IsBound())
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
ErrorCallback->Execute(RequestId, ErrorMessage);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
PendingTimeoutCallbacks.Remove(RequestId);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// Nettoyer les callbacks
|
|
|
|
|
|
PendingCallbacks.Remove(RequestId);
|
|
|
|
|
|
|
|
|
|
|
|
// Broadcaster l'événement Blueprint
|
|
|
|
|
|
OnTrackedRequestFailed.Broadcast(RequestId, RequestType, ErrorMessage);
|
|
|
|
|
|
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("Failed tracked request %s: %s"), *RequestId.ToString(), *ErrorMessage);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
void UDTFluxNetworkSubsystem::SendQueuedRequest(const FDTFluxQueuedRequest& QueuedRequest)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
2025-07-08 16:50:31 +02:00
|
|
|
|
// Générer le message JSON à partir de la requête
|
|
|
|
|
|
FString Message = QueuedRequest.Serialize();
|
|
|
|
|
|
|
|
|
|
|
|
if (Message.IsEmpty())
|
|
|
|
|
|
{
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Error, TEXT("Failed to serialize queued request %s"),
|
|
|
|
|
|
*QueuedRequest.RequestId.ToString());
|
|
|
|
|
|
FailTrackedRequest(QueuedRequest.RequestId, TEXT("Serialization failed"), QueuedRequest.RequestType);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Dirty trick to fix Case (comme dans l'original)
|
|
|
|
|
|
Message = Message.Replace(TEXT("Id"), TEXT("ID"), ESearchCase::CaseSensitive);
|
|
|
|
|
|
|
|
|
|
|
|
UE_LOG(logDTFluxNetwork, Log, TEXT("Sending queued request %s: %s"), *QueuedRequest.RequestId.ToString(), *Message);
|
|
|
|
|
|
|
|
|
|
|
|
// Envoyer via WebSocket
|
|
|
|
|
|
SendMessage(Message);
|
2025-06-29 19:04:36 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-08 16:50:31 +02:00
|
|
|
|
|
2025-07-03 17:28:51 +02:00
|
|
|
|
FString UDTFluxNetworkSubsystem::ConstructWsAddress(const FString& Address, const FString& Path, const int& Port)
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
FString NewAddress;
|
2025-07-08 16:50:31 +02:00
|
|
|
|
if (!Address.Contains("ws://") && !Address.Contains("wss://"))
|
2025-06-29 19:04:36 +02:00
|
|
|
|
{
|
|
|
|
|
|
NewAddress += FString("ws://");
|
|
|
|
|
|
}
|
2025-07-08 16:50:31 +02:00
|
|
|
|
NewAddress += Address + FString(":") + FString::FromInt(Port) + Path;
|
2025-06-29 19:04:36 +02:00
|
|
|
|
return NewAddress;
|
|
|
|
|
|
// UE_LOG(logDTFluxNetwork, Log, TEXT("NewAddress : %s"), *NewAddress);
|
|
|
|
|
|
}
|