Adds Custom DataAsset UI + Added Request buttons for RaceDatas/TeamList/Rankings request to ApiStatus Tab + Addes Tracked Requests For Rankings + Added Utils Module For Blueprint Utilities Functions
This commit is contained in:
166
Source/DTFluxNetwork/Public/DTFluxQueuedManager.h
Normal file
166
Source/DTFluxNetwork/Public/DTFluxQueuedManager.h
Normal file
@ -0,0 +1,166 @@
|
||||
// Fill out your copyright notice in the Description page of Project Settings.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "Containers/Queue.h"
|
||||
#include "Tickable.h"
|
||||
#include "Struct/DTFluxRequestStructs.h"
|
||||
#include "Struct/DTFluxServerResponseStruct.h"
|
||||
#include "Types/Enum/DTFluxCoreEnum.h"
|
||||
#include "DTFluxQueuedManager.generated.h"
|
||||
|
||||
/**
|
||||
* @brief Structure représentant une requête en file d'attente avec ses métadonnées
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FDTFluxQueuedRequest : public FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
/** L'identifiant unique de la requête */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
||||
FGuid RequestId;
|
||||
|
||||
/** L'heure à laquelle la requête a été envoyée */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
||||
FDateTime CreatedAt;
|
||||
|
||||
/** Le type de requête */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
||||
EDTFluxApiDataType RequestType = EDTFluxRequestType::None;
|
||||
|
||||
/** Identifiant de la compétition (ContestId) */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
||||
int32 ContestId = -1;
|
||||
|
||||
/** Identifiant de l'étape (StageId) */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
||||
int32 StageId = -1;
|
||||
|
||||
/** Identifiant du split (SplitId) */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
||||
int32 SplitId = -1;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "DTFlux|Request")
|
||||
FString RawResponse = "";
|
||||
|
||||
/** Délai maximum avant que la requête soit considérée comme expirée (en secondes) */
|
||||
UPROPERTY(BlueprintReadWrite, Category = "DTFlux|Request")
|
||||
float TimeoutSeconds = 2.0f;
|
||||
|
||||
/** Determine si la requête peut être mise en cache */
|
||||
UPROPERTY(BlueprintReadWrite, Category = "DTFlux|Request")
|
||||
bool bIsCacheable = false;
|
||||
|
||||
/** Validité du cache si bIsCacheable est mis à true après reception de la réponse (en secondes) */
|
||||
UPROPERTY(BlueprintReadWrite, Category = "DTFlux|Request")
|
||||
float CachedValidity = 50.0f;
|
||||
|
||||
/** Indicateur si la requête a reçu une réponse */
|
||||
UPROPERTY(BlueprintReadWrite, Category = "DTFlux|Request")
|
||||
bool bHasReceivedResponse = false;
|
||||
|
||||
/** Constructeur par défaut */
|
||||
FDTFluxQueuedRequest()
|
||||
{
|
||||
RequestId = FGuid::NewGuid();
|
||||
CreatedAt = FDateTime::Now();
|
||||
}
|
||||
|
||||
/** Constructeur avec paramètres */
|
||||
FDTFluxQueuedRequest(EDTFluxRequestType InRequestType, int32 InContestId = -1, int32 InStageId = -1,
|
||||
int32 InSplitId = -1)
|
||||
: RequestType(InRequestType)
|
||||
, ContestId(InContestId)
|
||||
, StageId(InStageId)
|
||||
, SplitId(InSplitId)
|
||||
{
|
||||
RequestId = FGuid::NewGuid();
|
||||
CreatedAt = FDateTime::Now();
|
||||
}
|
||||
|
||||
bool operator==(const FDTFluxQueuedRequest& Left) const
|
||||
{
|
||||
return RequestId == Left.RequestId;
|
||||
}
|
||||
|
||||
bool operator!=(const FDTFluxQueuedRequest& Left) const
|
||||
{
|
||||
return RequestId != Left.RequestId;
|
||||
}
|
||||
|
||||
|
||||
const FString Serialize() const;
|
||||
|
||||
/** Vérifie si la requête a expiré */
|
||||
bool HasTimedOut() const
|
||||
{
|
||||
return (FDateTime::Now() - CreatedAt).GetTotalSeconds() > TimeoutSeconds;
|
||||
}
|
||||
|
||||
|
||||
/** Vérifie si cette requête correspond aux paramètres spécifiés */
|
||||
bool Matches(EDTFluxRequestType InRequestType, int32 InContestId = -1, int32 InStageId = -1,
|
||||
int32 InSplitId = -1) const
|
||||
{
|
||||
return RequestType == InRequestType &&
|
||||
(InContestId == -1 || ContestId == InContestId) &&
|
||||
(InStageId == -1 || StageId == InStageId) &&
|
||||
(InSplitId == -1 || SplitId == InSplitId);
|
||||
}
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRequestTimedOut, const FDTFluxQueuedRequest&, TimedOutRequest);
|
||||
|
||||
/**
|
||||
* @brief Classe Tickable gérant les requêtes WebSockets qui ne sont pas traçables nativement par l'API.
|
||||
* Cette classe utilise TQueue pour gérer efficacement les requêtes en attente et vérifie leur état dans le tick.
|
||||
*/
|
||||
UCLASS()
|
||||
class DTFLUXNETWORK_API UDTFluxQueuedManager : public UObject, public FTickableGameObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** Constructeur par défaut */
|
||||
UDTFluxQueuedManager();
|
||||
virtual ~UDTFluxQueuedManager() override;
|
||||
void Initialize();
|
||||
FGuid QueueRequest(EDTFluxRequestType RequestType, int32 ContestId = -1, int32 StageId = -1, int32 SplitId = -1,
|
||||
const FString& RawMessage = "");
|
||||
bool MarkRequestAsResponded(const FGuid& TargetRequestGuid);
|
||||
bool MarkRequestAsResponded(const FDTFluxQueuedRequest& TargetRequest);
|
||||
bool IsRequestPending(EDTFluxRequestType RequestType, int32 ContestId = -1, int32 StageId = -1, int32 SplitId = -1);
|
||||
FDTFluxQueuedRequest* GetRequestPending(EDTFluxRequestType RequestType, int32 ContestId = -1, int32 StageId = -1,
|
||||
int32 SplitId = -1);
|
||||
const FDTFluxQueuedRequest* GetRequest(const FGuid& SearchedGuid);
|
||||
int32 GetPendingRequestCount();
|
||||
int32 CleanupTimedOutRequests();
|
||||
int32 CleanCashedRequests();
|
||||
void ClearAllRequests();
|
||||
// bool TryProcessResponse(const FDTFluxServerResponse& Response);
|
||||
|
||||
|
||||
// Interface FTickableGameObject
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
virtual bool IsTickable() const override;
|
||||
virtual TStatId GetStatId() const override;
|
||||
virtual bool IsTickableWhenPaused() const override { return true; }
|
||||
virtual bool IsTickableInEditor() const override { return true; }
|
||||
// Interface ~FTickableGameObject
|
||||
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category = "DTFlux|Network")
|
||||
FOnRequestTimedOut OnRequestTimedOut;
|
||||
|
||||
private:
|
||||
TQueue<FDTFluxQueuedRequest, EQueueMode::Mpsc> PendingRequestsQueue;
|
||||
TQueue<FDTFluxQueuedRequest, EQueueMode::Mpsc> CompletedRequestsQueue;
|
||||
TQueue<FDTFluxQueuedRequest, EQueueMode::Mpsc> TimedOutRequestsQueue;
|
||||
|
||||
bool bIsInitialized;
|
||||
float CheckInterval;
|
||||
float TimeSinceLastCheck;
|
||||
};
|
||||
@ -15,9 +15,13 @@ USTRUCT()
|
||||
struct FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Path = "";
|
||||
|
||||
FDateTime CreatedAt = FDateTime::Now();
|
||||
FGuid RequestId = FGuid::NewGuid();
|
||||
};
|
||||
|
||||
/**
|
||||
@ -25,11 +29,13 @@ public:
|
||||
* RaceData represents all data concerning the Race and its different Contests, Stages and Splits.
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxRaceDataRequest: public FDTFluxRequestBase
|
||||
struct FDTFluxRaceDataRequest : public FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
FDTFluxRaceDataRequest(){
|
||||
FDTFluxRaceDataRequest()
|
||||
{
|
||||
Path = "race-datas";
|
||||
}
|
||||
};
|
||||
@ -39,11 +45,13 @@ public:
|
||||
* TeamList is the list of participants of the events
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxTeamListRequest: public FDTFluxRequestBase
|
||||
struct FDTFluxTeamListRequest : public FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
FDTFluxTeamListRequest(){
|
||||
FDTFluxTeamListRequest()
|
||||
{
|
||||
Path = "team-list";
|
||||
}
|
||||
};
|
||||
@ -52,16 +60,17 @@ public:
|
||||
* Struct representing a Ranking json request object for a specific to the server
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxContestRankingRequest: public FDTFluxRequestBase
|
||||
struct FDTFluxContestRankingRequest : public FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
public:
|
||||
FDTFluxContestRankingRequest()
|
||||
{
|
||||
Path = "contest-ranking";
|
||||
ContestID = -1;
|
||||
}
|
||||
|
||||
FDTFluxContestRankingRequest(int InContestID)
|
||||
{
|
||||
Path = "contest-ranking";
|
||||
@ -76,10 +85,10 @@ public:
|
||||
* Struct representing a Ranking json request object for a specific Stage to the server
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxStageRankingRequest: public FDTFluxRequestBase
|
||||
struct FDTFluxStageRankingRequest : public FDTFluxRequestBase
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
public:
|
||||
FDTFluxStageRankingRequest()
|
||||
{
|
||||
@ -88,6 +97,7 @@ public:
|
||||
StageID = -1;
|
||||
SplitID = -1;
|
||||
}
|
||||
|
||||
FDTFluxStageRankingRequest(int InContestID, int InStageId)
|
||||
{
|
||||
Path = "stage-ranking";
|
||||
@ -102,18 +112,16 @@ public:
|
||||
int StageID;
|
||||
UPROPERTY()
|
||||
int SplitID;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Struct representing a Ranking json request object for a specific Split to the server
|
||||
*/
|
||||
USTRUCT()
|
||||
struct FDTFluxSplitRankingRequest: public FDTFluxStageRankingRequest
|
||||
struct FDTFluxSplitRankingRequest : public FDTFluxStageRankingRequest
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
|
||||
public:
|
||||
FDTFluxSplitRankingRequest()
|
||||
{
|
||||
@ -122,6 +130,7 @@ public:
|
||||
StageID = -1;
|
||||
SplitID = -1;
|
||||
}
|
||||
|
||||
FDTFluxSplitRankingRequest(int InContestID, int InStageId, int InSplitId)
|
||||
{
|
||||
Path = "stage-ranking";
|
||||
@ -129,5 +138,4 @@ public:
|
||||
StageID = InStageId;
|
||||
SplitID = InSplitId;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@ -4,13 +4,38 @@
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "UObject/Object.h"
|
||||
#include "DTFluxNetworkModule.h"
|
||||
#include "DTFluxRaceDataServerResponse.h"
|
||||
#include "DTFluxRankingServerResponse.h"
|
||||
#include "DTFluxSplitSensorServerResponse.h"
|
||||
#include "JsonObjectConverter.h"
|
||||
#include "Types/Enum/DTFluxCoreEnum.h"
|
||||
#include "Types/Objects/UDTFluxParticipantFactory.h"
|
||||
#include "Types/Struct/DTFluxRaceDataStructs.h"
|
||||
#include "Types/Struct/DTFluxRankingStructs.h"
|
||||
#include "Types/Struct/DTFluxSplitSensor.h"
|
||||
#include "DTFluxServerResponseStruct.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
* Enum pour indiquer le statut du parsing
|
||||
*/
|
||||
UENUM(BlueprintType)
|
||||
enum class EDTFluxResponseStatus : uint8
|
||||
{
|
||||
Unset = 0b00000000 UMETA(DisplayName="Unset"),
|
||||
Success = 0b10000000 UMETA(DisplayName="Success"),
|
||||
JsonParseError = 0b00000001 UMETA(DisplayName="JsonParseError"),
|
||||
ServerError = 0b00000010 UMETA(DisplayName="ServerError"),
|
||||
InvalidType = 0b00000100 UMETA(DisplayName="InvalidType"),
|
||||
MissingData = 0b00001000 UMETA(DisplayName="MissingData"),
|
||||
DataError = 0b00010000 UMETA(DisplayName="MissingData"),
|
||||
UnknownError = 0b00100000 UMETA(DisplayName="UnknownError")
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Struct representing a mixed root json server response
|
||||
* Struct representing a mixed root json server response with integrated parsing capabilities
|
||||
*/
|
||||
USTRUCT()
|
||||
struct DTFLUXNETWORK_API FDTFluxServerResponse
|
||||
@ -20,35 +45,76 @@ struct DTFLUXNETWORK_API FDTFluxServerResponse
|
||||
public:
|
||||
UPROPERTY()
|
||||
FString Type = "";
|
||||
|
||||
UPROPERTY()
|
||||
int Code = -1;
|
||||
|
||||
UPROPERTY()
|
||||
FString Message = "";
|
||||
|
||||
UPROPERTY()
|
||||
FString Trigger = "";
|
||||
|
||||
UPROPERTY()
|
||||
int ContestID = -1;
|
||||
|
||||
UPROPERTY()
|
||||
int StageID = -1;
|
||||
|
||||
UPROPERTY()
|
||||
int SplitID = -1;
|
||||
|
||||
UPROPERTY()
|
||||
FDateTime ReceivedAt;
|
||||
|
||||
UPROPERTY()
|
||||
FString RawMessage;
|
||||
|
||||
UPROPERTY()
|
||||
FName RequestId = FName("");
|
||||
|
||||
UPROPERTY()
|
||||
FText FailureReason;
|
||||
|
||||
|
||||
// === CONSTRUCTEURS ===
|
||||
FDTFluxServerResponse();
|
||||
FDTFluxServerResponse(const FString& JsonMessage, EDTFluxResponseStatus& OutStatus, bool bLogErrors = true);
|
||||
static FDTFluxServerResponse CreateFromJson(const FString& JsonMessage, bool bLogErrors = true);
|
||||
|
||||
// === MÉTHODES DE PARSING ===
|
||||
|
||||
EDTFluxResponseStatus TryParse(bool bLogErrors = true);
|
||||
|
||||
bool ParseTeamListResponse(FDTFluxTeamListDefinition& OutTeamList);
|
||||
bool ParseTeamUpdateResponse(FDTFluxTeamListDefinition& OutTeamUpdate);
|
||||
bool ParseRaceData(FDTFluxRaceData& OutRaceData);
|
||||
bool ParseContestRanking(FDTFluxContestRankings& OutContestRankings);
|
||||
bool ParseStageRankingResponse(FDTFluxStageRankings& OutStageRankings);
|
||||
bool ParseSplitRankingResponse(FDTFluxSplitRankings& OutSplitRankings);
|
||||
bool ParseStatusUpdateResponse(FDTFluxTeamStatusUpdate& OutStatusUpdate);
|
||||
bool ParseSplitSensorResponse(TArray<FDTFluxSplitSensorInfo>& OutSplitSensorInfos);
|
||||
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
bool IsValidResponse() const { return Code == -1; }
|
||||
bool IsSuccessfullyParsed() const { return ParsingStatus == EDTFluxResponseStatus::Success; }
|
||||
EDTFluxResponseStatus GetParsingStatus() const { return ParsingStatus; }
|
||||
EDTFluxApiDataType GetResponseType() const { return ApiDataType; }
|
||||
FString GetDataType() const { return Type; }
|
||||
bool ContainsDataType(const FString& DataType) const { return Type.Contains(DataType); }
|
||||
FString ToDebugString() const;
|
||||
void ShowDebug(const bool bShouldPrintRawMessage = false) const;
|
||||
FString GetErrorMessage() const;
|
||||
|
||||
private:
|
||||
// === DONNÉES INTERNES ===
|
||||
EDTFluxApiDataType ApiDataType;
|
||||
// Statut du parsing initial
|
||||
EDTFluxResponseStatus ParsingStatus = EDTFluxResponseStatus::Unset;
|
||||
|
||||
// === MÉTHODES PRIVÉES DE PARSING ===
|
||||
bool ParseJsonObject(TSharedPtr<FJsonObject>& OutJsonObject) const;
|
||||
bool ValidateResponseType(const FString& ExpectedType) const;
|
||||
EDTFluxResponseStatus InitializeFromJson(const FString& JsonMessage, bool bLogErrors);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "DTFluxQueuedManager.h"
|
||||
#include "Struct/DTFluxServerResponseStruct.h"
|
||||
#include "Subsystems/EngineSubsystem.h"
|
||||
#include "Types/DTFluxNetworkSettingsTypes.h"
|
||||
@ -14,12 +15,24 @@
|
||||
#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(FOnDTFluxRequestResponse, const FGuid&, const FString&);
|
||||
DECLARE_DELEGATE_TwoParams(FOnDTFluxRequestTimeout, const FGuid&, const FString&);
|
||||
// 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);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -27,25 +40,28 @@ UCLASS(Blueprintable)
|
||||
class DTFLUXNETWORK_API UDTFluxNetworkSubsystem : public UEngineSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
|
||||
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;
|
||||
@ -53,32 +69,40 @@ public:
|
||||
|
||||
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 FDTFluxParticipant& /*ParticipantToUpdate*/);
|
||||
DECLARE_DELEGATE_OneParam(FOnTeamUpdateReceived, const FDTFluxTeamListDefinition& /*ParticipantToUpdate*/);
|
||||
FOnTeamUpdateReceived OnTeamUpdateReceived;
|
||||
|
||||
FOnTeamUpdateReceived& OnReceivedTeamUpdate()
|
||||
{
|
||||
return OnTeamUpdateReceived;
|
||||
@ -86,6 +110,7 @@ public:
|
||||
|
||||
DECLARE_DELEGATE_OneParam(FOnTeamStatusUpdateReceived, const FDTFluxTeamStatusUpdate& /*TeamToUpdate*/);
|
||||
FOnTeamStatusUpdateReceived OnTeamStatusUpdateReceived;
|
||||
|
||||
FOnTeamStatusUpdateReceived& OnReceivedTeamStatusUpdate()
|
||||
{
|
||||
return OnTeamStatusUpdateReceived;
|
||||
@ -99,13 +124,41 @@ public:
|
||||
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,
|
||||
FOnDTFluxRequestResponse OnCompleted, FOnDTFluxRequestTimeout OnTimeout,
|
||||
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")
|
||||
void SendRequest(const EDTFluxRequestType RequestType, int InContestId = -1, int InStageId = -1, int InSplitId = -1);
|
||||
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
|
||||
|
||||
// === 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;
|
||||
@ -114,9 +167,22 @@ protected:
|
||||
|
||||
|
||||
private:
|
||||
// === CONFIGURATION ===
|
||||
FDTFluxWsSettings WsSettings;
|
||||
FDTFluxHttpSettings HttpSettings;
|
||||
|
||||
UPROPERTY()
|
||||
UDTFluxQueuedManager* QueueManager;
|
||||
|
||||
// === MAPPING DES CALLBACKS C++ ===
|
||||
TMap<FGuid, FOnDTFluxRequestResponse> PendingCallbacks;
|
||||
TMap<FGuid, FOnDTFluxRequestTimeout> PendingTimeoutCallbacks;
|
||||
|
||||
// === CLIENTS RÉSEAU ===
|
||||
FDTFluxWebSocketClientSP WsClient = nullptr;
|
||||
FDTFluxHttpClientSP HttpClient = nullptr;
|
||||
|
||||
// === MÉTHODES DE CONFIGURATION ===
|
||||
UFUNCTION()
|
||||
void WsSettingsChanged(const FDTFluxWsSettings& NewWsSettings);
|
||||
UFUNCTION()
|
||||
@ -124,40 +190,46 @@ private:
|
||||
void ReconnectWs(const FName WsClientId);
|
||||
void ReconnectHttp(const FName WsClientId);
|
||||
|
||||
// === GESTION DES ÉVÉNEMENTS WEBSOCKET ===
|
||||
void RegisterWebSocketEvents();
|
||||
void RegisterHttpEvents();
|
||||
void UnregisterWebSocketEvents();
|
||||
void UnregisterHttpEvents();
|
||||
|
||||
void OnWebSocketConnected_Subsystem();
|
||||
void OnWebSocketConnectionError_Subsystem(const FString& Error);
|
||||
void OnWebSocketClosedEvent_Subsystem(int32 StatusCode , const FString& Reason, bool bWasClean);
|
||||
void ParseTeamListResponse(const FDTFluxServerResponse& ServerResponse);
|
||||
void ParseRaceData(const FDTFluxServerResponse& Response);
|
||||
void ParseContestRanking(const FDTFluxServerResponse& Response);
|
||||
void ParseStageRankingResponse(const FDTFluxServerResponse& Response);
|
||||
void ParseSplitRankingResponse(const FDTFluxServerResponse& Response);
|
||||
void ParseStatusUpdateResponse(const FDTFluxServerResponse& Response);
|
||||
void ParseSplitSensorResponse(const FDTFluxServerResponse& Response);
|
||||
void OnWebSocketMessageEvent_Subsystem(const FString& MessageString);
|
||||
void OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent);
|
||||
|
||||
// TODO : Allow multiple instances of network clients.
|
||||
// // For Future use of Multi-Connections
|
||||
// TArray<FDTFluxWebSocketClientSP> WsClients;
|
||||
// // For Future use of Multi-Connections
|
||||
// TArray<FDTFluxHttpClientSP> HttpClient;
|
||||
// Fo now we jest stick to only one client for each protocol
|
||||
void OnWebSocketClosedEvent_Subsystem(int32 StatusCode, const FString& Reason, bool bWasClean);
|
||||
|
||||
FDelegateHandle OnWsConnectedEventDelegateHandle;
|
||||
FDelegateHandle OnWsConnectionErrorEventDelegateHandle;
|
||||
FDelegateHandle OnWsClosedEventDelegateHandle;
|
||||
FDelegateHandle OnWsMessageEventDelegateHandle;
|
||||
FDelegateHandle OnWsMessageSentEventDelegateHandle;
|
||||
|
||||
FDTFluxWebSocketClientSP WsClient = nullptr;
|
||||
FDTFluxHttpClientSP HttpClient = nullptr;
|
||||
|
||||
// === 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);
|
||||
|
||||
// === GESTION DES REQUÊTES TRACKÉES ===
|
||||
UFUNCTION()
|
||||
void OnRequestTimedOut_Internal(const FDTFluxQueuedRequest& TimedOutRequest);
|
||||
bool TryMatchResponseToQueuedRequest(const 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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user