244 lines
9.5 KiB
C++
244 lines
9.5 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "DTFluxQueuedManager.h"
|
|
#include "Struct/DTFluxServerResponseStruct.h"
|
|
#include "Subsystems/EngineSubsystem.h"
|
|
#include "Types/DTFluxNetworkSettingsTypes.h"
|
|
#include "Types/Enum/DTFluxCoreEnum.h"
|
|
#include "Types/Struct/DTFluxRaceDataStructs.h"
|
|
#include "Types/Struct/DTFluxRankingStructs.h"
|
|
#include "Types/Struct/DTFluxSplitSensor.h"
|
|
#include "Types/Struct/DTFluxTeamListStruct.h"
|
|
#include "DTFluxNetworkSubsystem.generated.h"
|
|
|
|
|
|
class FDTFluxWebSocketClient;
|
|
class UDTFluxQueuedManager;
|
|
typedef TSharedPtr<FDTFluxWebSocketClient> FDTFluxWebSocketClientSP;
|
|
class FDTFluxHttpClient;
|
|
typedef TSharedPtr<FDTFluxHttpClient> FDTFluxHttpClientSP;
|
|
|
|
|
|
// Delegates pour les requêtes avec callback
|
|
DECLARE_DELEGATE_TwoParams(FOnDTFluxRequestResponseError, const FGuid&, const FString&);
|
|
DECLARE_DELEGATE_TwoParams(FOnDTFluxTrackedRequestResponse, const FGuid&, FDTFluxServerResponse&);
|
|
DECLARE_DELEGATE_TwoParams(FOnDTFluxTrackedRequestTimeout, const FGuid&, const FString& /*ErrorMessage*/);
|
|
// Delegates Blueprint pour les requêtes avec tracking
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnDTFluxTrackedRequestCompleted, const FGuid&, RequestId,
|
|
EDTFluxApiDataType, RequestType, const FString&, ResponseData);
|
|
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnDTFluxTrackedRequestFailed, const FGuid&, RequestId,
|
|
EDTFluxApiDataType, RequestType, const FString&, ErrorMessage);
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
UCLASS(Blueprintable)
|
|
class DTFLUXNETWORK_API UDTFluxNetworkSubsystem : public UEngineSubsystem
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
UPROPERTY()
|
|
EDTFluxConnectionStatus WsStatus = EDTFluxConnectionStatus::Unset;
|
|
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWebSocketConnected);
|
|
|
|
UPROPERTY(BlueprintAssignable, Category="DTFlux|Network")
|
|
FOnWebSocketConnected OnWebSocketConnected;
|
|
|
|
DECLARE_DELEGATE_OneParam(FOnRaceDataReceived, const FDTFluxRaceData& /*RaceDataDefinition*/);
|
|
FOnRaceDataReceived OnRaceDataReceived;
|
|
|
|
FOnRaceDataReceived& OnReceivedRaceData()
|
|
{
|
|
return OnRaceDataReceived;
|
|
};
|
|
|
|
// === DELEGATES POUR LES DONNÉES REÇUES (PUSH) ===
|
|
DECLARE_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition& /*TeamListDefinition*/);
|
|
FOnTeamListReceived OnTeamListReceived;
|
|
|
|
FOnTeamListReceived& OnReceivedTeamList()
|
|
{
|
|
return OnTeamListReceived;
|
|
};
|
|
|
|
DECLARE_DELEGATE_OneParam(FOnStageRankingReceived, const FDTFluxStageRankings& /*StageRankings*/);
|
|
FOnStageRankingReceived OnStageRankingReceived;
|
|
|
|
FOnStageRankingReceived& OnReceivedStageRanking()
|
|
{
|
|
return OnStageRankingReceived;
|
|
}
|
|
|
|
DECLARE_DELEGATE_OneParam(FOnSplitRankingReceived, const FDTFluxSplitRankings& /*SplitRankings*/);
|
|
FOnSplitRankingReceived OnSplitRankingReceived;
|
|
|
|
FOnSplitRankingReceived& OnReceivedSplitRanking()
|
|
{
|
|
return OnSplitRankingReceived;
|
|
}
|
|
|
|
DECLARE_DELEGATE_OneParam(FOnContestRankingReceived, const FDTFluxContestRankings& /*ContestRankings*/);
|
|
FOnContestRankingReceived OnContestRankingReceived;
|
|
|
|
FOnContestRankingReceived& OnReceivedContestRanking()
|
|
{
|
|
return OnContestRankingReceived;
|
|
};
|
|
|
|
// === DELEGATES POUR LES DONNÉES REÇUES (PULL) ===
|
|
DECLARE_DELEGATE_OneParam(FOnSplitSensorReceived, const FDTFluxSplitSensorInfo& /*ContestRankings*/);
|
|
FOnSplitSensorReceived OnSplitSensorReceived;
|
|
|
|
FOnSplitSensorReceived& OnReceivedSplitSensor()
|
|
{
|
|
return OnSplitSensorReceived;
|
|
};
|
|
|
|
DECLARE_DELEGATE_OneParam(FOnTeamUpdateReceived, const FDTFluxTeamListDefinition& /*ParticipantToUpdate*/);
|
|
FOnTeamUpdateReceived OnTeamUpdateReceived;
|
|
|
|
FOnTeamUpdateReceived& OnReceivedTeamUpdate()
|
|
{
|
|
return OnTeamUpdateReceived;
|
|
};
|
|
|
|
DECLARE_DELEGATE_OneParam(FOnTeamStatusUpdateReceived, const FDTFluxTeamStatusUpdate& /*TeamToUpdate*/);
|
|
FOnTeamStatusUpdateReceived OnTeamStatusUpdateReceived;
|
|
|
|
FOnTeamStatusUpdateReceived& OnReceivedTeamStatusUpdate()
|
|
{
|
|
return OnTeamStatusUpdateReceived;
|
|
};
|
|
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
|
void Connect();
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
|
void Disconnect();
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
|
void Reconnect();
|
|
|
|
|
|
// === REQUÊTES AVEC QUEUE ET TRACKING ===
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Tracked Requests")
|
|
FGuid SendTrackedRequest(EDTFluxApiDataType RequestType, int32 ContestId = -1, int32 StageId = -1,
|
|
int32 SplitId = -1, float TimeoutSeconds = 30.0f);
|
|
|
|
FGuid SendTrackedRequestWithCallback(EDTFluxApiDataType RequestType, int32 ContestId, int32 StageId, int32 SplitId,
|
|
FOnDTFluxTrackedRequestResponse OnCompleted,
|
|
FOnDTFluxTrackedRequestTimeout OnTimeout,
|
|
TOptional<FOnDTFluxRequestResponseError> OnError = TOptional<
|
|
FOnDTFluxRequestResponseError>(),
|
|
float TimeoutSeconds = 30.0f);
|
|
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Tracked Requests")
|
|
bool GetTrackedRequest(const FGuid& RequestId, FDTFluxQueuedRequest& OutRequest) const;
|
|
const FDTFluxQueuedRequest* GetTrackedRequestPtr(const FGuid& RequestId) const;
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Tracked Requests", CallInEditor)
|
|
bool HasRequestReceivedResponse(const FGuid& RequestId) const;
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Tracked Requests")
|
|
FString GetRequestResponseData(const FGuid& RequestId) const;
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Tracked Requests")
|
|
bool IsRequestPending(EDTFluxApiDataType RequestType, int32 ContestId = -1, int32 StageId = -1,
|
|
int32 SplitId = -1) const;
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Tracked Requests")
|
|
int32 GetPendingRequestCount() const;
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Tracked Requests")
|
|
UDTFluxQueuedManager* GetQueueManager() const;
|
|
|
|
// === EVENTS BLUEPRINT POUR LE TRACKING ===
|
|
UPROPERTY(BlueprintAssignable, Category="DTFlux|Tracked Requests")
|
|
FOnDTFluxTrackedRequestCompleted OnTrackedRequestCompleted;
|
|
UPROPERTY(BlueprintAssignable, Category="DTFlux|Tracked Requests")
|
|
FOnDTFluxTrackedRequestFailed OnTrackedRequestFailed;
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
|
|
|
|
// === REQUÊTES DIRECTES (LEGACY) ===
|
|
void SendRequest(const EDTFluxApiDataType RequestType, int InContestId = -1, int InStageId = -1,
|
|
int InSplitId = -1);
|
|
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
|
void SendMessage(const FString& Message);
|
|
|
|
protected:
|
|
// ~Subsystem Interface
|
|
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
|
virtual void Deinitialize() override;
|
|
// ~Subsystem Interface
|
|
|
|
|
|
private:
|
|
// === CONFIGURATION ===
|
|
FDTFluxWsSettings WsSettings;
|
|
FDTFluxHttpSettings HttpSettings;
|
|
|
|
UPROPERTY()
|
|
UDTFluxQueuedManager* QueueManager;
|
|
|
|
// === MAPPING DES CALLBACKS C++ ===
|
|
TMap<FGuid, FOnDTFluxTrackedRequestResponse> PendingCallbacks;
|
|
TMap<FGuid, FOnDTFluxTrackedRequestTimeout> PendingTimeoutCallbacks;
|
|
TMap<FGuid, FOnDTFluxRequestResponseError> PendingErrorCallbacks;
|
|
|
|
// === CLIENTS RÉSEAU ===
|
|
FDTFluxWebSocketClientSP WsClient = nullptr;
|
|
FDTFluxHttpClientSP HttpClient = nullptr;
|
|
|
|
// === MÉTHODES DE CONFIGURATION ===
|
|
UFUNCTION()
|
|
void WsSettingsChanged(const FDTFluxWsSettings& NewWsSettings);
|
|
UFUNCTION()
|
|
void HttpSettingsChanged(const FDTFluxHttpSettings& NewHttpSettings);
|
|
void ReconnectWs(const FName WsClientId);
|
|
void ReconnectHttp(const FName WsClientId);
|
|
|
|
// === GESTION DES ÉVÉNEMENTS WEBSOCKET ===
|
|
void RegisterWebSocketEvents();
|
|
void UnregisterWebSocketEvents();
|
|
|
|
void OnWebSocketConnected_Subsystem();
|
|
void OnWebSocketConnectionError_Subsystem(const FString& Error);
|
|
void OnWebSocketClosedEvent_Subsystem(int32 StatusCode, const FString& Reason, bool bWasClean);
|
|
|
|
FDelegateHandle OnWsConnectedEventDelegateHandle;
|
|
FDelegateHandle OnWsConnectionErrorEventDelegateHandle;
|
|
FDelegateHandle OnWsClosedEventDelegateHandle;
|
|
FDelegateHandle OnWsMessageEventDelegateHandle;
|
|
FDelegateHandle OnWsMessageSentEventDelegateHandle;
|
|
|
|
// === GESTION DES ÉVÉNEMENTS HTTP ===
|
|
void RegisterHttpEvents();
|
|
void UnregisterHttpEvents();
|
|
|
|
// === PARSING DES RÉPONSES ===
|
|
void ParseTeamListResponse(FDTFluxServerResponse& ServerResponse);
|
|
void ParseRaceData(FDTFluxServerResponse& Response);
|
|
void ParseContestRanking(FDTFluxServerResponse& Response);
|
|
void ParseStageRankingResponse(FDTFluxServerResponse& Response);
|
|
void ParseSplitRankingResponse(FDTFluxServerResponse& Response);
|
|
void ParseStatusUpdateResponse(FDTFluxServerResponse& Response);
|
|
void ParseSplitSensorResponse(FDTFluxServerResponse& Response);
|
|
EDTFluxResponseStatus ProcessPushMessage(FDTFluxServerResponse& Response);
|
|
|
|
void Parse(FDTFluxServerResponse& Response);
|
|
void OnWebSocketMessageEvent_Subsystem(const FString& MessageString);
|
|
void OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent);
|
|
bool CleanRequestCallbacks(const FGuid& RequestId);
|
|
|
|
// === GESTION DES REQUÊTES TRACKÉES ===
|
|
UFUNCTION()
|
|
void OnRequestTimedOut_Internal(const FDTFluxQueuedRequest& TimedOutRequest);
|
|
bool TryMatchResponseToQueuedRequest(FDTFluxServerResponse& Response);
|
|
void CompleteTrackedRequest(const FGuid& RequestId, const FString& ResponseData, EDTFluxRequestType RequestType);
|
|
void FailTrackedRequest(const FGuid& RequestId, const FString& ErrorMessage, EDTFluxRequestType RequestType);
|
|
void SendQueuedRequest(const FDTFluxQueuedRequest& QueuedRequest);
|
|
|
|
// === UTILITAIRES ===
|
|
static FString ConstructWsAddress(const FString& Address, const FString& Path, const int& Port);
|
|
};
|