Adding Status and Last server response handled but not tested

This commit is contained in:
2025-07-03 17:28:51 +02:00
parent 2855fa1e98
commit fa5493adcf
43 changed files with 2035 additions and 379 deletions

View File

@ -17,6 +17,24 @@ FDTFluxWebSocketClient::FDTFluxWebSocketClient()
FDTFluxWebSocketClient::LastId++;
}
bool FDTFluxWebSocketClient::CanSend() const
{
return Ws.IsValid();
}
TSharedPtr<FDTFluxWebSocketClient> FDTFluxWebSocketClient::GetClient(
const TArray<TSharedPtr<FDTFluxWebSocketClient>> InClients, const FName InName)
{
for(auto Client: InClients)
{
if(Client->ClientId == InName)
{
return Client;
}
}
return nullptr;
}
void FDTFluxWebSocketClient::Connect()
{
Ws = FWebSocketsModule::Get().CreateWebSocket(WsAddress);
@ -80,7 +98,10 @@ void FDTFluxWebSocketClient::AddError(const FDTFluxWsClientError Error)
void FDTFluxWebSocketClient::Send(const FString& Message) const
{
Ws->Send(Message);
if(Ws.IsValid())
{
Ws->Send(Message);
}
}

View File

@ -12,18 +12,31 @@
#include "Struct/DTFluxRequestStructs.h"
#include "Struct/DTFluxRaceDataServerResponse.h"
#include "Struct/DTFluxRankingServerResponse.h"
#include "Struct/DTFluxSplitSensorServerResponse.h"
#include "Struct/DTFluxTeamListServerResponse.h"
#include "Types/Objects/UDTFluxParticipantFactory.h"
#include "Types/Struct/DTFluxRaceDataStructs.h"
#include "Types/Struct/DTFluxSplitSensor.h"
void UFDTFluxNetworkSubsystem::Connect()
void UDTFluxNetworkSubsystem::Connect()
{
WsClient->SetAddress(ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port));
WsClient->Connect();
WsClient->SetAddress(ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port));
WsClient->Connect();
}
void UFDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType, int InContestId, int InStageId,
int InSplitId)
void UDTFluxNetworkSubsystem::Disconnect()
{
WsClient->Disconnect();
}
void UDTFluxNetworkSubsystem::Reconnect()
{
ReconnectWs(FName("Ws_Client_0"));
}
void UDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType, int InContestId, int InStageId,
int InSplitId)
{
FString Message;
switch (RequestType)
@ -52,12 +65,24 @@ void UFDTFluxNetworkSubsystem::SendRequest(const EDTFluxRequestType RequestType,
SendMessage(Message);
}
void UFDTFluxNetworkSubsystem::SendMessage(const FString& Message)
void UDTFluxNetworkSubsystem::SendMessage(const FString& Message)
{
WsClient->Send(Message);
UE_LOG(logDTFluxCore, Warning, TEXT("Sending Message %s"), *Message);
if(WsClient.IsValid() && WsClient->CanSend())
{
WsClient->Send(Message);
UE_LOG(logDTFluxNetwork, Log, TEXT("Can send request"));
}
else
{
UE_LOG(logDTFluxNetwork, Error, TEXT("[Websocket Not Connected]. Connect before sending requests..."));
}
}
void UFDTFluxNetworkSubsystem::Initialize(FSubsystemCollectionBase& Collection)
void UDTFluxNetworkSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
FDTFluxCoreModule& DTFluxCore = FModuleManager::Get().LoadModuleChecked<FDTFluxCoreModule>("DTFluxCore");
@ -81,22 +106,17 @@ void UFDTFluxNetworkSubsystem::Initialize(FSubsystemCollectionBase& Collection)
}
}
void UFDTFluxNetworkSubsystem::Deinitialize()
void UDTFluxNetworkSubsystem::Deinitialize()
{
Super::Deinitialize();
}
void UFDTFluxNetworkSubsystem::WsSettingsChanged(const FDTFluxWsSettings& NewWsSettings)
void UDTFluxNetworkSubsystem::WsSettingsChanged(const FDTFluxWsSettings& NewWsSettings)
{
// TODO Implement a ClientSelector To retrieve impacted WsClients and populate changes or maybe create a delegate
bool bNeedsReload = WsSettings != NewWsSettings;
WsSettings = NewWsSettings;
// UE_LOG(logDTFluxNetwork, Warning, TEXT("WSocket Settings Changed \n\t Address : %s Path : %s Port : %i\n\tbShouldConnectAtStatup : %s, bShouldAutoReconnectOnClosed %s, bShouldAutoReconnectOnError %s"),
// *NewWsSettings.Address, *NewWsSettings.Path, NewWsSettings.Port,
// NewWsSettings.bShouldConnectAtStartup ? TEXT("True") : TEXT("False"),
// NewWsSettings.bShouldAutoReconnectOnClosed ? TEXT("True") : TEXT("False"),
// NewWsSettings.bShouldAutoReconnectOnError ? TEXT("True") : TEXT("False") );
if( bNeedsReload || WsSettings.bShouldConnectAtStartup)
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("WSocket Settings needs Reloding client"))
@ -105,46 +125,46 @@ void UFDTFluxNetworkSubsystem::WsSettingsChanged(const FDTFluxWsSettings& NewWsS
}
void UFDTFluxNetworkSubsystem::HttpSettingsChanged(const FDTFluxHttpSettings& NewHttpSettings)
void UDTFluxNetworkSubsystem::HttpSettingsChanged(const FDTFluxHttpSettings& NewHttpSettings)
{
// TODO Implement a ClientSelector To retrieve impacted HttpClients and populate changes or maybe create a delegate
HttpSettings = NewHttpSettings;
}
void UFDTFluxNetworkSubsystem::ReconnectWs(const FName WsClientId)
void UDTFluxNetworkSubsystem::ReconnectWs(const FName WsClientId)
{
FString NewAddress = ConstructWsAddress(WsSettings.Address, WsSettings.Path, WsSettings.Port);
WsClient->SetAddress(NewAddress);
WsClient->Reconnect();
}
void UFDTFluxNetworkSubsystem::ReconnectHttp(const FName WsClientId)
void UDTFluxNetworkSubsystem::ReconnectHttp(const FName WsClientId)
{
}
void UFDTFluxNetworkSubsystem::RegisterWebSocketEvents()
void UDTFluxNetworkSubsystem::RegisterWebSocketEvents()
{
OnWsConnectedEventDelegateHandle =
WsClient->RegisterConnectedEvent().AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem);
WsClient->RegisterConnectedEvent().AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem);
OnWsConnectionErrorEventDelegateHandle =
WsClient->RegisterConnectionError()
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem);
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem);
OnWsClosedEventDelegateHandle =
WsClient->RegisterClosedEvent()
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem);
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem);
OnWsMessageEventDelegateHandle =
WsClient->RegisterMessageEvent()
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem);
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem);
OnWsMessageSentEventDelegateHandle =
WsClient->RegisterMessageSentEvent()
.AddUObject(this, &UFDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem);
.AddUObject(this, &UDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem);
}
void UFDTFluxNetworkSubsystem::RegisterHttpEvents()
void UDTFluxNetworkSubsystem::RegisterHttpEvents()
{
}
void UFDTFluxNetworkSubsystem::UnregisterWebSocketEvents()
void UDTFluxNetworkSubsystem::UnregisterWebSocketEvents()
{
if(OnWsConnectedEventDelegateHandle.IsValid())
{
@ -168,35 +188,219 @@ void UFDTFluxNetworkSubsystem::UnregisterWebSocketEvents()
}
}
void UFDTFluxNetworkSubsystem::UnregisterHttpEvents()
void UDTFluxNetworkSubsystem::UnregisterHttpEvents()
{
}
void UFDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem()
void UDTFluxNetworkSubsystem::OnWebSocketConnected_Subsystem()
{
WsStatus = EDTFluxConnectionStatus::Connected;
OnWebSocketConnected.Broadcast();
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Is Connected with %s"), *WsClient->GetAddress())
}
void UFDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem(const FString& Error)
void UDTFluxNetworkSubsystem::OnWebSocketConnectionError_Subsystem(const FString& Error)
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Error with %s : %s"), *WsClient->GetAddress(), *Error);
WsStatus = EDTFluxConnectionStatus::Error;
if(WsSettings.bShouldAutoReconnectOnError)
{
WsClient->Reconnect();
}
}
void UFDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem(int32 StatusCode, const FString& Reason, bool bWasClean)
void UDTFluxNetworkSubsystem::OnWebSocketClosedEvent_Subsystem(int32 StatusCode, const FString& Reason, bool bWasClean)
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Error with %s :\n Reason : %s \tStatusCode : %i, bWasClean : %s"),
*WsClient->GetAddress(), *Reason, StatusCode, bWasClean ? TEXT("True") : TEXT("False"));
WsStatus = EDTFluxConnectionStatus::Closed;
}
void UDTFluxNetworkSubsystem::ParseTeamListResponse(const FDTFluxServerResponse& ServerResponse)
{
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(ServerResponse.RawMessage);
if (!FJsonSerializer::Deserialize(Reader, JsonObject) || !JsonObject.IsValid())
{
UE_LOG(logDTFluxNetwork, Error, TEXT("JSON invalide : %s"), *ServerResponse.RawMessage);
return;
}
const TArray<TSharedPtr<FJsonValue>>* DataArray;
if (!JsonObject->TryGetArrayField(TEXT("datas"), DataArray))
{
UE_LOG(logDTFluxNetwork, Error, TEXT("Aucun champ 'datas' trouvé dans le team-list"));
return;
}
FDTFluxTeamListDefinition TeamListDefinition;
for (const TSharedPtr<FJsonValue>& Value : *DataArray)
{
if (Value->Type == EJson::Object)
{
const TSharedPtr<FJsonObject> Item = Value->AsObject();
FDTFluxParticipant Participant;
UDTFluxParticipantFactory::CreateFromJsonCpp(Item, Participant);
TeamListDefinition.Participants.Add(Participant);
}
}
UE_LOG(logDTFluxNetwork, Warning, TEXT("Inserting %i Participants [%s]"), TeamListDefinition.Participants.Num(),
OnTeamListReceived.ExecuteIfBound(TeamListDefinition) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
}
void UDTFluxNetworkSubsystem::ParseRaceData(const FDTFluxServerResponse& Response)
{
FDTFluxRaceDataResponse RaceData;
if(FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxRaceDataResponse>(Response.RawMessage, &RaceData))
{
//convert
FDTFluxRaceData RaceDataDefinition;
for(auto Contest : RaceData.Datas)
{
FDTFluxContest NewContest;
NewContest.Name = Contest.Name;
NewContest.ContestId = Contest.Id;
NewContest.Date = Contest.Date;
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s] Starting at %s \nStages: \n"), Contest.Id, *Contest.Date.ToString(),*Contest.Name);
for(auto Stage : Contest.Stages)
{
FDTFluxStage NewStage;
NewStage.StageId = Stage.Id;
NewStage.Name = Stage.Name;
FString StartTimeFString = FString::Printf(TEXT("%s %s"),
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
*Stage.StartTime
);
FString EndTimeFString = FString::Printf(TEXT("%s %s"),
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
*Stage.EndTime
);
FString CutOffFString = FString::Printf(TEXT("%s %s"),
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
*Stage.CutOff
);
FDateTime::Parse(StartTimeFString, NewStage.StartTime);
FDateTime::Parse(EndTimeFString, NewStage.EndTime);
FDateTime::Parse(CutOffFString, NewStage.CutOff);
NewContest.Stages.Add(NewStage);
UE_LOG(logDTFluxNetwork, Warning, TEXT("Stage %i [%s]: \nSTartTime Received [%s] -> Datetime[%s], CutOff [%s], EndTime [%s] \n"), Stage.Id, *Stage.Name,
*Stage.StartTime, *NewStage.StartTime.ToString(), *NewStage.CutOff.ToString(), *NewStage.EndTime.ToString());
}
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s]\nSplits: \n"), Contest.Id, *Contest.Name);
for(auto Split: Contest.Splits)
{
FDTFluxSplit NewSplit;
NewSplit.SplitId = Split.Id;
NewSplit.Name = Split.Name;
NewContest.Splits.Add(NewSplit);
UE_LOG(logDTFluxNetwork, Warning, TEXT("Split %i [%s]: \n"), Split.Id, *Split.Name);
}
RaceDataDefinition.Datas.Add(NewContest);
}
UE_LOG(logDTFluxNetwork, Warning, TEXT("Sending %i Contests, [%s]"), RaceDataDefinition.Datas.Num(),
OnRaceDataReceived.ExecuteIfBound(RaceDataDefinition) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
return;
}
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseRaceData() for JSON Response : %s"), *Response.RawMessage);
}
void UDTFluxNetworkSubsystem::ParseContestRanking(const FDTFluxServerResponse& Response)
{
FDTFluxContestRankingResponse ContestRankingResponse;
if(FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxContestRankingResponse>(Response.RawMessage, &ContestRankingResponse))
{
FDTFluxContestRankings ContestRankings;
ContestRankings.ContestId = ContestRankingResponse.ContestID;
for(auto& RankingItem : ContestRankingResponse.Datas)
{
FDTFluxContestRanking Temp = RankingItem;
ContestRankings.Rankings.Add(Temp);
}
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws ContestRanking Data Sent for Contest %i, [%s]"), ContestRankings.ContestId,
OnContestRankingReceived.ExecuteIfBound(ContestRankings) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
return;
}
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseContestRanking() for JSON Response : %s"), *Response.RawMessage);
}
void UDTFluxNetworkSubsystem::ParseStageRankingResponse(const FDTFluxServerResponse& Response)
{
FDTFluxStageRankingResponse RankingResponse;
if(FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxStageRankingResponse>(Response.RawMessage, &RankingResponse))
{
FDTFluxStageRankings NewRankings;
NewRankings.ContestId = Response.ContestID;
NewRankings.StageId = Response.StageID;
NewRankings.Rankings = static_cast<TArray<FDTFluxDetailedRankingItem>>(RankingResponse.Datas);
UE_LOG(logDTFluxNetwork, Warning, TEXT("StageRanking Data Sent for Contest %i, Stage %i\n[Result] : %s"),
NewRankings.ContestId, NewRankings.StageId,
OnStageRankingReceived.ExecuteIfBound(NewRankings) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED")
);
return;
}
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseStageRankingResponse() for JSON Response : %s"), *Response.RawMessage);
}
void UDTFluxNetworkSubsystem::ParseSplitRankingResponse(const FDTFluxServerResponse& Response)
{
FDTFluxSplitRankingResponse SplitRankingResponse;
if(FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxSplitRankingResponse>(Response.RawMessage, &SplitRankingResponse))
{
FDTFluxSplitRankings NewSplitRankings;
NewSplitRankings.ContestId = Response.ContestID;
NewSplitRankings.StageId = Response.StageID;
NewSplitRankings.SplitId = Response.SplitID;
NewSplitRankings.Rankings = static_cast<TArray<FDTFluxDetailedRankingItem>>(SplitRankingResponse.Datas);
UE_LOG(logDTFluxNetwork, Warning, TEXT("SplitRanking Data Sent for Contest %i, Stage %i and Split %i\n[Result] : %s"),
NewSplitRankings.ContestId, NewSplitRankings.StageId, NewSplitRankings.SplitId,
OnSplitRankingReceived.ExecuteIfBound(NewSplitRankings) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
return;
}
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseSplitRankingResponse() for JSON Response : %s"), *Response.RawMessage);
}
void UDTFluxNetworkSubsystem::ParseStatusUpdateResponse(const FDTFluxServerResponse& Response)
{
FDTFluxTeamStatusUpdate StatusUpdateResponse;
if (FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxTeamStatusUpdate>(Response.RawMessage, &StatusUpdateResponse))
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("Status Update for bib %i \n[Result] : %s\n"),
StatusUpdateResponse.Bib,
OnTeamStatusUpdateReceived.ExecuteIfBound(StatusUpdateResponse) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
return;
}
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseStatusUpdateResponse() for JSON Response : %s"), *Response.RawMessage);
}
void UDTFluxNetworkSubsystem::ParseSplitSensorResponse(const FDTFluxServerResponse& Response)
{
FDTFluxSplitSensorResponse SplitSensorResponse;
if(FJsonObjectConverter::JsonObjectStringToUStruct(Response.RawMessage, &SplitSensorResponse))
{
for(const auto& SplitSensorInfoResponse : SplitSensorResponse.Datas)
{
FDTFluxSplitSensorInfo NewSplitSensorInfo;
NewSplitSensorInfo.Bib = SplitSensorInfoResponse.Bib;
NewSplitSensorInfo.ContestId = SplitSensorInfoResponse.ContestID;
NewSplitSensorInfo.StageId = SplitSensorInfoResponse.StageID;
NewSplitSensorInfo.SplitId = SplitSensorInfoResponse.SplitID;
NewSplitSensorInfo.Time = SplitSensorInfoResponse.Time;
UE_LOG(logDTFluxNetwork, Warning, TEXT("Status Update for bib %i in Contest %i, Stage %i in split %i\n[Result] : %s\n"),
NewSplitSensorInfo.Bib, NewSplitSensorInfo.ContestId, NewSplitSensorInfo.StageId, NewSplitSensorInfo.SplitId,
OnSplitSensorReceived.ExecuteIfBound(NewSplitSensorInfo) ? TEXT("SUCCESS_SEND") : TEXT("NOT_BOUNDED"));
}
}
UE_LOG(logDTFluxNetwork, Error, TEXT("ParseSplitSensorResponse() failed for JSON Response : %s"), *Response.RawMessage);
}
//TODO reforge API to keep track of Requests
void UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString& MessageString)
void UDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString& MessageString)
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws %s :\nMessage Received : %s"), *WsClient->GetAddress(), *MessageString);
UE_LOG(logDTFluxNetwork, Warning, TEXT("Client %s :\nMessage Received : %s"), *WsClient->GetAddress(), *MessageString);
//Do Something With the message
FDTFluxServerResponse Response;
Response.ReceivedAt = FDateTime::Now();
@ -209,97 +413,50 @@ void UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString&
// return DataReceived.Broadcast(Response);
if(Response.Type.Contains("race-data"))
{
FDTFluxRaceDataResponse RaceData;
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxRaceDataResponse>(Response.RawMessage, &RaceData);
//convert
FDTFluxRaceData RaceDataDefinition;
for(auto Contest : RaceData.Datas)
{
FDTFluxContest NewContest;
NewContest.Name = Contest.Name;
NewContest.ContestId = Contest.Id;
NewContest.Date = Contest.Date;
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s] Starting at %s \nStages: \n"), Contest.Id, *Contest.Date.ToString(),*Contest.Name);
for(auto Stage : Contest.Stages)
{
FDTFluxStage NewStage;
NewStage.StageId = Stage.Id;
NewStage.Name = Stage.Name;
FString StartTimeFString = FString::Printf(TEXT("%s %s"),
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
*Stage.StartTime
);
FString EndTimeFString = FString::Printf(TEXT("%s %s"),
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
*Stage.EndTime
);
FString CutOffFString = FString::Printf(TEXT("%s %s"),
*NewContest.Date.ToFormattedString(TEXT("%Y-%m-%d")),
*Stage.CutOff
);
FDateTime::Parse(StartTimeFString, NewStage.StartTime);
FDateTime::Parse(EndTimeFString, NewStage.EndTime);
FDateTime::Parse(CutOffFString, NewStage.CutOff);
NewContest.Stages.Add(NewStage);
UE_LOG(logDTFluxNetwork, Warning, TEXT("Stage %i [%s]: \nSTartTime Received [%s] -> Datetime[%s], CutOff [%s], EndTime [%s] \n"), Stage.Id, *Stage.Name,
*Stage.StartTime, *NewStage.StartTime.ToString(), *NewStage.CutOff.ToString(), *NewStage.EndTime.ToString());
}
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest %i [%s]\nSplits: \n"), Contest.Id, *Contest.Name);
for(auto Split: Contest.Splits)
{
FDTFluxSplit NewSplit;
NewSplit.SplitId = Split.Id;
NewSplit.Name = Split.Name;
NewContest.Splits.Add(NewSplit);
UE_LOG(logDTFluxNetwork, Warning, TEXT("Split %i [%s]: \n"), Split.Id, *Split.Name);
}
RaceDataDefinition.Datas.Add(NewContest);
}
UE_LOG(logDTFluxNetwork, Warning, TEXT("Sending %i Contests"), RaceDataDefinition.Datas.Num());
return OnRaceDataReceived.Broadcast(RaceDataDefinition);
UE_LOG(logDTFluxNetwork, Warning, TEXT("Race-Data Received"));
return ParseRaceData(Response);
}
if(Response.Type.Contains("team-list"))
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Team-List Data"));
FDTFluxTeamListDefinition TeamListDefinition;
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxTeamListDefinition>(Response.RawMessage, &TeamListDefinition);
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Team-List Data Sent"));
return OnTeamListReceived.Broadcast(TeamListDefinition);
UE_LOG(logDTFluxNetwork, Warning, TEXT("Team-List Received"));
return ParseTeamListResponse(Response);
}
if(Response.Type.Contains("contest-ranking"))
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Contest-Ranking Data"));
FDTFluxContestRankingResponse ContestRankingResponse;
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxContestRankingResponse>(Response.RawMessage, &ContestRankingResponse);
FDTFluxContestRankings ContestRankings;
ContestRankings.ContestId = ContestRankingResponse.ContestID;
for(auto& RankingItem : ContestRankingResponse.Datas)
{
FDTFluxContestRanking Temp = RankingItem;
ContestRankings.Rankings.Add(Temp);
}
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws ContestRanking Data Sent for Contest %i"), ContestRankings.ContestId);
return OnContestRankingReceived.Broadcast(ContestRankings);
UE_LOG(logDTFluxNetwork, Warning, TEXT("Contest-Ranking Received"));
return ParseContestRanking(Response);
}
if(Response.Type.Contains("stage-ranking") )
{
// StageRanking
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws Stage-Ranking Data"));
FDTFluxStageRankingResponse StageRankingResponse;
FJsonObjectConverter::JsonObjectStringToUStruct<FDTFluxStageRankingResponse>(Response.RawMessage, &StageRankingResponse);
FDTFluxStageRankings StageRankings;
StageRankings.ContestId = StageRankingResponse.ContestId;
StageRankings.StageId = StageRankingResponse.StageId;
StageRankings.SplitId = StageRankingResponse.SplitId;
for(FDTFluxStageRanking& InRanking : StageRankingResponse.Datas)
if(Response.SplitID == -1)
{
FDTFluxStageRanking Temp = InRanking;
StageRankings.Rankings.Add(InRanking);
// StageRanking
UE_LOG(logDTFluxNetwork, Warning, TEXT("Stage-Ranking Data"));
ParseStageRankingResponse(Response);
}
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws StageRanking Data Sent for Contest %i and Stage %i\n[Result] : %s"),
StageRankings.ContestId, StageRankings.StageId, OnStageRankingReceived.ExecuteIfBound(StageRankings) ? TEXT("Executed") : TEXT("Not Bound !!!"));
return;
else
{
// StageRanking
UE_LOG(logDTFluxNetwork, Warning, TEXT("Split-Ranking Data"));
return ParseSplitRankingResponse(Response);
}
}
if(Response.Type.Contains("split-sensor"))
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("split-sensor Data"));
ParseSplitSensorResponse(Response);
}
if(Response.Type.Contains("status-update"))
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("status-update Data"));
ParseStatusUpdateResponse(Response);
}
if(Response.Type.Contains("team-update"))
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("team-update Data"));
ParseTeamListResponse(Response);
}
}
@ -309,12 +466,12 @@ void UFDTFluxNetworkSubsystem::OnWebSocketMessageEvent_Subsystem(const FString&
}
void UFDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent)
void UDTFluxNetworkSubsystem::OnWebSocketMessageSentEvent_Subsystem(const FString& MessageSent)
{
UE_LOG(logDTFluxNetwork, Warning, TEXT("Ws %s :\nMessage Sent: %s"), *WsClient->GetAddress(), *MessageSent);
}
FString UFDTFluxNetworkSubsystem::ConstructWsAddress(const FString& Address, const FString& Path, const int& Port)
FString UDTFluxNetworkSubsystem::ConstructWsAddress(const FString& Address, const FString& Path, const int& Port)
{
FString NewAddress;
if( !Address.Contains("ws://") && !Address.Contains("wss://"))
@ -324,4 +481,5 @@ FString UFDTFluxNetworkSubsystem::ConstructWsAddress(const FString& Address, con
NewAddress +=Address + FString(":") + FString::FromInt(Port) + Path;
return NewAddress;
// UE_LOG(logDTFluxNetwork, Log, TEXT("NewAddress : %s"), *NewAddress);
}

View File

@ -52,18 +52,12 @@ class DTFLUXNETWORK_API FDTFluxWebSocketClient : public TSharedFromThis<FDTFluxW
public:
FDTFluxWebSocketClient();
bool CanSend() const;
static TSharedPtr<FDTFluxWebSocketClient> GetClient(const TArray<TSharedPtr<FDTFluxWebSocketClient>> InClients, const FName InName)
{
for(auto Client: InClients)
{
if(Client->ClientId == InName)
{
return Client;
}
}
return nullptr;
}
static TSharedPtr<FDTFluxWebSocketClient> GetClient(const TArray<TSharedPtr<FDTFluxWebSocketClient>> InClients, const FName InName);
void Connect();
void Reconnect();

View File

@ -33,7 +33,18 @@ public:
};
USTRUCT(BlueprintType)
struct DTFLUXNETWORK_API FDTFluxStageRankingResponseItem : public FDTFluxStageRanking
struct DTFLUXNETWORK_API FDTFluxStageRankingResponseItem : public FDTFluxDetailedRankingItem
{
GENERATED_BODY()
public:
UPROPERTY()
FString Type = "team-stage-ranking";
};
USTRUCT(BlueprintType)
struct DTFLUXNETWORK_API FDTFluxSplitRankingResponseItem : public FDTFluxDetailedRankingItem
{
GENERATED_BODY()
@ -43,7 +54,7 @@ public:
};
USTRUCT(BlueprintType)
struct DTFLUXNETWORK_API FDTFluxStageRankingResponse : public FDTFluxStageRankings
struct DTFLUXNETWORK_API FDTFluxStageRankingResponse
{
GENERATED_BODY()
@ -56,3 +67,18 @@ public:
// ReSharper disable once IdentifierTypo
TArray<FDTFluxStageRankingResponseItem> Datas;
};
USTRUCT(BlueprintType)
struct DTFLUXNETWORK_API FDTFluxSplitRankingResponse
{
GENERATED_BODY()
public:
UPROPERTY()
FString Type = "stage-ranking";
UPROPERTY()
// ReSharper disable once IdentifierTypo
TArray<FDTFluxSplitRankingResponseItem> Datas;
};

View File

@ -25,10 +25,7 @@ public:
int SplitID;
UPROPERTY()
FString Time = "-";
UPROPERTY()
FString Gap = "-";
UPROPERTY()
int Rank;
};
USTRUCT(BlueprintType)

View File

@ -6,8 +6,11 @@
#include "Struct/DTFluxServerResponseStruct.h"
#include "Subsystems/EngineSubsystem.h"
#include "Types/DTFluxNetworkSettingsTypes.h"
#include "Types/Enum/DTfluxCoreEnum.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"
@ -21,53 +24,79 @@ typedef TSharedPtr<FDTFluxHttpClient> FDTFluxHttpClientSP;
*
*/
UCLASS(Blueprintable)
class DTFLUXNETWORK_API UFDTFluxNetworkSubsystem : public UEngineSubsystem
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_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnRaceDataReceived, const FDTFluxRaceData&, RaceDataDefinition);
DECLARE_DELEGATE_OneParam(FOnRaceDataReceived, const FDTFluxRaceData& /*RaceDataDefinition*/);
FOnRaceDataReceived OnRaceDataReceived;
FOnRaceDataReceived& OnReceivedRaceData()
{
return OnRaceDataReceived;
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition&, TeamListDefinition);
DECLARE_DELEGATE_OneParam(FOnTeamListReceived, const FDTFluxTeamListDefinition& /*TeamListDefinition*/);
FOnTeamListReceived OnTeamListReceived;
FOnTeamListReceived& OnReceivedTeamList()
{
return OnTeamListReceived;
};
DECLARE_DELEGATE_OneParam(FOnStageRankingReceived, const FDTFluxStageRankings&);
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_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnContestRankingReceived, const FDTFluxContestRankings&, ContestRankings);
DECLARE_DELEGATE_OneParam(FOnContestRankingReceived, const FDTFluxContestRankings& /*ContestRankings*/);
FOnContestRankingReceived OnContestRankingReceived;
FOnContestRankingReceived& OnReceivedContestRanking()
{
return OnContestRankingReceived;
};
DECLARE_DELEGATE_OneParam(FOnSplitSensorReceived, const FDTFluxSplitSensorInfo& /*ContestRankings*/);
FOnSplitSensorReceived OnSplitSensorReceived;
FOnSplitSensorReceived& OnReceivedSplitSensor()
{
return OnSplitSensorReceived;
};
DECLARE_DELEGATE_OneParam(FOnTeamUpdateReceived, const FDTFluxParticipant& /*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 Reconnect();
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
void Disconnect();
UFUNCTION(BlueprintCallable, Category="DTFlux|Network")
void Reconnect();
UFUNCTION(BlueprintCallable, Category="DTFlux|Core Subsystem")
@ -103,6 +132,13 @@ private:
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);