Files
DTFluxAPI/Source/DTFluxNetwork/Public/Subsystems/DTFluxNetworkSubsystem.h

271 lines
9.8 KiB
C
Raw Normal View History

2025-07-11 19:04:37 +02:00
// ================================================================================================
// DTFluxNetworkSubsystem.h - Interface UObject avec compatibilité Blueprint
// ================================================================================================
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/EngineSubsystem.h"
#include "Types/DTFluxNetworkSettingsTypes.h"
#include "Types/Enum/DTFluxCoreEnum.h"
2025-07-11 19:04:37 +02:00
#include "DTFluxQueuedManager.h"
#include "DTFluxNetworkSubsystem.generated.h"
2025-07-11 19:04:37 +02:00
// Forward declarations
class FDTFluxWebSocketClient;
2025-07-11 19:04:37 +02:00
class FDTFluxQueuedRequestManager;
typedef TSharedPtr<FDTFluxWebSocketClient> FDTFluxWebSocketClientSP;
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);
2025-07-11 19:04:37 +02:00
DECLARE_DELEGATE_OneParam(FOnRaceDataReceived, const FDTFluxRaceData& /*RaceDataDefinition*/);
DECLARE_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition& /*TeamListDefinition*/);
DECLARE_DELEGATE_OneParam(FOnStageRankingReceived, const FDTFluxStageRankings& /*StageRankings*/);
DECLARE_DELEGATE_OneParam(FOnSplitRankingReceived, const FDTFluxSplitRankings& /*SplitRankings*/);
DECLARE_DELEGATE_OneParam(FOnContestRankingReceived, const FDTFluxContestRankings& /*ContestRankings*/);
DECLARE_DELEGATE_OneParam(FOnSplitSensorReceived, const FDTFluxSplitSensorInfo& /*SplitSensorInfo*/);
DECLARE_DELEGATE_OneParam(FOnTeamUpdateReceived, const FDTFluxTeamListDefinition& /*ParticipantToUpdate*/);
DECLARE_DELEGATE_OneParam(FOnTeamStatusUpdateReceived, const FDTFluxTeamStatusUpdate& /*TeamToUpdate*/);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnWebSocketConnected);
UCLASS(Blueprintable)
class DTFLUXNETWORK_API UDTFluxNetworkSubsystem : public UEngineSubsystem
{
GENERATED_BODY()
public:
2025-07-11 19:04:37 +02:00
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Network")
EDTFluxConnectionStatus WsStatus = EDTFluxConnectionStatus::Unset;
2025-07-11 19:04:37 +02:00
/**
* Se connecter au serveur WebSocket
*/
UFUNCTION(BlueprintCallable, Category = "DTFlux|Network")
void Connect();
2025-07-11 19:04:37 +02:00
/**
* Se déconnecter du serveur WebSocket
*/
UFUNCTION(BlueprintCallable, Category = "DTFlux|Network")
void Disconnect();
2025-07-11 19:04:37 +02:00
/**
* Reconnecter au serveur WebSocket
*/
UFUNCTION(BlueprintCallable, Category = "DTFlux|Network")
void Reconnect();
2025-07-11 19:04:37 +02:00
/**
* Envoyer une requête trackée avec cache, timeout et retry
* @param RequestType Type de requête (ContestRanking, StageRanking, etc.)
* @param ContestId ID du contest (-1 si non applicable)
* @param StageId ID du stage (-1 si non applicable)
* @param SplitId ID du split (-1 si non applicable)
* @param TimeoutSeconds Timeout en secondes
* @param MaxRetries Nombre maximum de tentatives
* @param bEnableCache Activer le cache pour cette requête
* @return GUID de la requête pour le suivi
*/
UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests")
FGuid SendTrackedRequest(
EDTFluxApiDataType RequestType,
int32 ContestId = -1,
int32 StageId = -1,
int32 SplitId = -1,
float TimeoutSeconds = 5.0f,
int32 MaxRetries = 3,
bool bEnableCache = true
);
/**
* Envoyer une requête trackée avec callbacks C++ (non Blueprint)
* @param RequestType Type de requête
* @param ContestId ID du contest
* @param StageId ID du stage
* @param SplitId ID du split
* @param OnSuccess Callback appelé en cas de succès
* @param OnError Callback appelé en cas d'erreur
* @param TimeoutSeconds Timeout en secondes
* @param MaxRetries Nombre maximum de tentatives
* @param bEnableCache Activer le cache
* @return GUID de la requête
*/
FGuid SendTrackedRequestWithCallbacks(
EDTFluxApiDataType RequestType,
int32 ContestId,
int32 StageId,
int32 SplitId,
FOnDTFluxRequestSuccess& OnSuccess,
FOnDTFluxRequestError& OnError,
float TimeoutSeconds = 5.0f,
int32 MaxRetries = 3
2025-07-11 19:04:37 +02:00
);
2025-07-11 19:04:37 +02:00
UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests")
bool GetTrackedRequest(const FGuid& RequestId, FDTFluxTrackedRequest& OutRequest) const;
2025-07-11 19:04:37 +02:00
UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests")
bool HasRequestReceivedResponse(const FGuid& RequestId) const;
2025-07-11 19:04:37 +02:00
UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests")
FString GetRequestResponseData(const FGuid& RequestId) const;
2025-07-11 19:04:37 +02:00
UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests")
bool IsRequestPending(EDTFluxApiDataType RequestType, int32 ContestId = -1, int32 StageId = -1,
int32 SplitId = -1) const;
2025-07-11 19:04:37 +02:00
UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests")
int32 GetPendingRequestCount() const;
2025-07-11 19:04:37 +02:00
UFUNCTION(BlueprintCallable, Category = "DTFlux|Tracked Requests")
void GetRequestStatistics(int32& OutPending, int32& OutCompleted, int32& OutFailed) const;
2025-07-11 19:04:37 +02:00
UFUNCTION(BlueprintCallable, Category = "DTFlux|Legacy")
void SendRequest(const EDTFluxApiDataType RequestType, int InContestId = -1, int InStageId = -1,
int InSplitId = -1);
2025-07-11 19:04:37 +02:00
UFUNCTION(BlueprintCallable, Category = "DTFlux|Network")
void SendMessage(const FString& Message);
2025-07-11 19:04:37 +02:00
UPROPERTY(BlueprintAssignable, Category = "DTFlux|Network")
FOnWebSocketConnected OnWebSocketConnected;
2025-07-11 19:04:37 +02:00
UPROPERTY(BlueprintAssignable, Category = "DTFlux|Tracked Requests")
FOnDTFluxTrackedRequestCompleted OnTrackedRequestCompleted;
2025-07-11 19:04:37 +02:00
UPROPERTY(BlueprintAssignable, Category = "DTFlux|Tracked Requests")
FOnDTFluxTrackedRequestFailed OnTrackedRequestFailed;
2025-07-11 19:04:37 +02:00
FOnRaceDataReceived OnRaceDataReceived;
FOnTeamListReceived OnTeamListReceived;
FOnStageRankingReceived OnStageRankingReceived;
FOnSplitRankingReceived OnSplitRankingReceived;
FOnContestRankingReceived OnContestRankingReceived;
FOnSplitSensorReceived OnSplitSensorReceived;
FOnTeamUpdateReceived OnTeamUpdateReceived;
FOnTeamStatusUpdateReceived OnTeamStatusUpdateReceived;
2025-07-11 19:04:37 +02:00
FOnRaceDataReceived& OnReceivedRaceData() { return OnRaceDataReceived; }
FOnTeamListReceived& OnReceivedTeamList() { return OnTeamListReceived; }
FOnStageRankingReceived& OnReceivedStageRanking() { return OnStageRankingReceived; }
FOnSplitRankingReceived& OnReceivedSplitRanking() { return OnSplitRankingReceived; }
FOnContestRankingReceived& OnReceivedContestRanking() { return OnContestRankingReceived; }
FOnSplitSensorReceived& OnReceivedSplitSensor() { return OnSplitSensorReceived; }
FOnTeamUpdateReceived& OnReceivedTeamUpdate() { return OnTeamUpdateReceived; }
FOnTeamStatusUpdateReceived& OnReceivedTeamStatusUpdate() { return OnTeamStatusUpdateReceived; }
2025-07-11 19:04:37 +02:00
TSharedPtr<FDTFluxQueuedRequestManager> GetRequestManager() const { return RequestManager; }
protected:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
private:
FDTFluxWsSettings WsSettings;
FDTFluxWebSocketClientSP WsClient = nullptr;
2025-07-11 19:04:37 +02:00
TSharedPtr<FDTFluxQueuedRequestManager> RequestManager;
void RegisterWebSocketEvents();
void UnregisterWebSocketEvents() const;
void OnWebSocketConnected_Subsystem();
void OnWebSocketConnectionError_Subsystem(const FString& Error);
void OnWebSocketClosedEvent_Subsystem(int32 StatusCode, const FString& Reason, bool bWasClean);
2025-07-11 19:04:37 +02:00
void OnWebSocketMessageEvent_Subsystem(const FString& MessageString);
void OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent);
FDelegateHandle OnWsConnectedEventDelegateHandle;
FDelegateHandle OnWsConnectionErrorEventDelegateHandle;
FDelegateHandle OnWsClosedEventDelegateHandle;
FDelegateHandle OnWsMessageEventDelegateHandle;
FDelegateHandle OnWsMessageSentEventDelegateHandle;
2025-07-11 19:04:37 +02:00
/**
* Essayer de matcher une réponse à une requête trackée
* @param MessageString Message JSON reçu
* @return true si la réponse correspond à une requête trackée
*/
bool TryMatchResponseToQueuedRequest(const FString& MessageString);
/**
* Traiter une réponse en mode legacy
* @param MessageString Message JSON à traiter
*/
void ProcessLegacyResponse(const FString& MessageString);
/**
* Traiter une réponse déjà parsée
* @param ParsedResponse Réponse parsée à traiter
*/
void ProcessParsedResponse(TSharedPtr<FDTFluxServerResponse> ParsedResponse);
// === MÉTHODES DE PARSING LEGACY (pour compatibilité) ===
void ParseTeamListResponse(FDTFluxServerResponse& Response);
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);
2025-07-11 19:04:37 +02:00
/**
* Callback appelé quand une requête trackée se termine
*/
void OnRequestCompleted_Internal(const FDTFluxTrackedRequest& CompletedRequest);
/**
* Callback appelé quand une requête trackée échoue
*/
void OnRequestFailed_Internal(const FDTFluxTrackedRequest& FailedRequest);
/**
* Callback appelé quand les paramètres WebSocket changent
*/
UFUNCTION()
2025-07-11 19:04:37 +02:00
void WsSettingsChanged(const FDTFluxWsSettings& NewWsSettings);
/**
* Reconnecter le client WebSocket
*/
void ReconnectWs(const FName WsClientId);
2025-07-11 19:04:37 +02:00
/**
* Construire une adresse WebSocket complète
*/
static FString ConstructWsAddress(const FString& Address, const FString& Path, const int& Port);
2025-07-11 19:04:37 +02:00
/**
* Envoyer une requête trackée via le réseau
*/
void SendQueuedRequest(const FDTFluxTrackedRequest& QueuedRequest);
/**
* Déterminer si on doit utiliser le parsing asynchrone
*/
bool ShouldUseAsyncParsing(const FString& JsonData) const;
};