Imgui per entity works
Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com>
This commit is contained in:
@@ -79,7 +79,7 @@ ly_add_target(
|
||||
|
||||
# The "Multiplayer" target is used by clients and servers, Debug is used only on clients.
|
||||
ly_create_alias(NAME Multiplayer.Clients NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug)
|
||||
ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer)
|
||||
ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer Gem::Multiplayer.Debug)
|
||||
|
||||
if (PAL_TRAIT_BUILD_HOST_TOOLS)
|
||||
ly_add_target(
|
||||
|
||||
@@ -111,7 +111,6 @@ namespace Multiplayer
|
||||
int32_t bitIndex,
|
||||
TYPE& value,
|
||||
const char* name,
|
||||
AZ::EntityId entityId,
|
||||
NetComponentId componentId,
|
||||
PropertyIndex propertyIndex,
|
||||
MultiplayerStats& stats
|
||||
@@ -134,11 +133,11 @@ namespace Multiplayer
|
||||
{
|
||||
if (modifyRecord)
|
||||
{
|
||||
stats.RecordPropertyReceived(entityId, componentId, propertyIndex, updateSize);
|
||||
stats.RecordPropertyReceived(componentId, propertyIndex, updateSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.RecordPropertySent(entityId, componentId, propertyIndex, updateSize);
|
||||
stats.RecordPropertySent(componentId, propertyIndex, updateSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,9 @@ namespace Multiplayer
|
||||
AZStd::vector<ComponentStats> m_componentStats;
|
||||
|
||||
void ReserveComponentStats(NetComponentId netComponentId, uint16_t propertyCount, uint16_t rpcCount);
|
||||
void RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName);
|
||||
void RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName);
|
||||
void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName);
|
||||
void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, NetComponentId netComponentId);
|
||||
void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName);
|
||||
void RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes);
|
||||
void RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes);
|
||||
void RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes);
|
||||
|
||||
@@ -447,15 +447,18 @@ namespace Multiplayer
|
||||
|
||||
bool NetBindComponent::SerializeStateDeltaMessage(ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer)
|
||||
{
|
||||
GetMultiplayer()->GetStats().RecordEntitySerializeStart(GetEntityId(), GetEntity()->GetName().c_str());
|
||||
auto& stats = GetMultiplayer()->GetStats();
|
||||
stats.RecordEntitySerializeStart(serializer.GetSerializerMode(), GetEntityId(), GetEntity()->GetName().c_str());
|
||||
|
||||
bool success = true;
|
||||
for (auto iter = m_multiplayerSerializationComponentVector.begin(); iter != m_multiplayerSerializationComponentVector.end(); ++iter)
|
||||
{
|
||||
success &= (*iter)->SerializeStateDeltaMessage(replicationRecord, serializer);
|
||||
|
||||
stats.RecordComponentSerializeEnd(serializer.GetSerializerMode(), (*iter)->GetNetComponentId());
|
||||
}
|
||||
|
||||
GetMultiplayer()->GetStats().RecordEntitySerializeStop(GetEntityId(), GetEntity()->GetName().c_str());
|
||||
stats.RecordEntitySerializeStop(serializer.GetSerializerMode(), GetEntityId(), GetEntity()->GetName().c_str());
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <sstream>
|
||||
#include <AzCore/std/sort.h>
|
||||
|
||||
#pragma optimize("", off)
|
||||
|
||||
namespace MultiplayerDiagnostics
|
||||
{
|
||||
void MultiplayerDebugByteReporter::ReportBytes(size_t byteSize)
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
@@ -13,14 +13,16 @@
|
||||
|
||||
namespace MultiplayerDiagnostics
|
||||
{
|
||||
class MultilayerIPerEntityStats
|
||||
class MultiplayerIPerEntityStats
|
||||
{
|
||||
public:
|
||||
virtual ~MultilayerIPerEntityStats();
|
||||
AZ_RTTI(MultiplayerIPerEntityStats, "{91A1E4F0-8AE6-44B2-89DF-DA34134C408A}");
|
||||
|
||||
virtual void RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName) = 0;
|
||||
virtual void RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName) = 0;
|
||||
virtual void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes);
|
||||
virtual void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes);
|
||||
virtual void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) = 0;
|
||||
virtual void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) = 0;
|
||||
virtual void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) = 0;
|
||||
virtual void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0;
|
||||
virtual void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) = 0;
|
||||
virtual void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,23 +7,22 @@
|
||||
*/
|
||||
|
||||
#include "MultiplayerDebugPerEntityReporter.h"
|
||||
#include <GridMate/Replica/ReplicaChunk.h>
|
||||
#include <GridMate/Replica/ReplicaChunkDescriptor.h>
|
||||
#include <GridMate/Replica/RemoteProcedureCall.h>
|
||||
#include <Multiplayer/IMultiplayer.h>
|
||||
|
||||
#if defined(IMGUI_ENABLED)
|
||||
#include <imgui/imgui.h>
|
||||
#endif
|
||||
|
||||
#pragma optimize("", off)
|
||||
|
||||
namespace MultiplayerDiagnostics
|
||||
{
|
||||
#if defined(IMGUI_ENABLED)
|
||||
static const ImVec4 k_ImGuiTomato = ImVec4(1.0f, 0.4f, 0.3f, 1.0f);
|
||||
static const ImVec4 k_ImGuiKhaki = ImVec4(0.9f, 0.8f, 0.5f, 1.0f);
|
||||
static const ImVec4 k_ImGuiCyan = ImVec4(0.5f, 1.0f, 1.0f, 1.0f);
|
||||
static const ImVec4 k_ImGuiDusk = ImVec4(0.7f, 0.7f, 1.0f, 1.0f);
|
||||
static const ImVec4 k_ImGuiWhite = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
static const ImVec4 k_ImGuiKhaki = ImVec4(0.9f, 0.8f, 0.5f, 1.0f);
|
||||
static const ImVec4 k_ImGuiCyan = ImVec4(0.5f, 1.0f, 1.0f, 1.0f);
|
||||
static const ImVec4 k_ImGuiDusk = ImVec4(0.7f, 0.7f, 1.0f, 1.0f);
|
||||
static const ImVec4 k_ImGuiWhite = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
template <typename Reporter>
|
||||
@@ -111,291 +110,103 @@ namespace MultiplayerDiagnostics
|
||||
}
|
||||
#endif
|
||||
|
||||
MultiplayerDebugPerEntityReporter::MultiplayerDebugPerEntityReporter ()
|
||||
{
|
||||
//GridMate::Debug::CarrierDrillerBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
MultiplayerDebugPerEntityReporter::~MultiplayerDebugPerEntityReporter()
|
||||
{
|
||||
/*GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect();
|
||||
GridMate::Debug::CarrierDrillerBus::Handler::BusDisconnect();*/
|
||||
}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnReceiveReplicaBegin(GridMate::Replica*, const void*, size_t)
|
||||
//{
|
||||
// m_currentReceivingEntityReport.Reset();
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnReceiveReplicaEnd(GridMate::Replica* replica)
|
||||
//{
|
||||
// m_receivingEntityReports[replica->GetDebugName()].Combine(m_currentReceivingEntityReport);
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnReceiveReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex)
|
||||
//{
|
||||
// AZ_UNUSED(chunk);
|
||||
// AZ_UNUSED(chunkIndex);
|
||||
// m_currentReceivingEntityReport.ReportFragmentEnd();
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnReceiveDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex,
|
||||
// GridMate::DataSetBase* dataSet, GridMate::PeerId, GridMate::PeerId, const void*, size_t len)
|
||||
//{
|
||||
// m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len);
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnReceiveRpc (GridMate::ReplicaChunkBase* chunk,
|
||||
// AZ::u32 chunkIndex,
|
||||
// GridMate::Internal::RpcRequest* rpc,
|
||||
// GridMate::PeerId from,
|
||||
// GridMate::PeerId to,
|
||||
// const void* data,
|
||||
// size_t len)
|
||||
//{
|
||||
// AZ_UNUSED( from );
|
||||
// AZ_UNUSED( to );
|
||||
// AZ_UNUSED( data );
|
||||
|
||||
// m_currentReceivingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len);
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnSendReplicaBegin (GridMate::Replica*)
|
||||
//{
|
||||
// m_currentSendingEntityReport.Reset();
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnSendReplicaEnd (GridMate::Replica* replica, const void*, size_t)
|
||||
//{
|
||||
// m_sendingEntityReports[replica->GetDebugName()].Combine(m_currentSendingEntityReport);
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnSendReplicaChunkEnd (GridMate::ReplicaChunkBase* chunk,
|
||||
// AZ::u32 chunkIndex,
|
||||
// const void*,
|
||||
// size_t)
|
||||
//{
|
||||
// AZ_UNUSED(chunk);
|
||||
// AZ_UNUSED(chunkIndex);
|
||||
// m_currentSendingEntityReport.ReportFragmentEnd();
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnSendDataSet (GridMate::ReplicaChunkBase* chunk,
|
||||
// AZ::u32 chunkIndex,
|
||||
// GridMate::DataSetBase* dataSet,
|
||||
// GridMate::PeerId,
|
||||
// GridMate::PeerId,
|
||||
// const void*,
|
||||
// size_t len)
|
||||
//{
|
||||
// m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetDataSetName(chunk, dataSet), len);
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnSendRpc (GridMate::ReplicaChunkBase* chunk,
|
||||
// AZ::u32 chunkIndex,
|
||||
// GridMate::Internal::RpcRequest* rpc,
|
||||
// GridMate::PeerId,
|
||||
// GridMate::PeerId,
|
||||
// const void*,
|
||||
// size_t len)
|
||||
//{
|
||||
// m_currentSendingEntityReport.ReportField(chunkIndex, chunk->GetDescriptor()->GetChunkName(), chunk->GetDescriptor()->GetRpcName(chunk, rpc->m_rpc), len);
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnIncomingConnection (GridMate::Carrier*, GridMate::ConnectionID)
|
||||
//{
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnFailedToConnect (GridMate::Carrier*,
|
||||
// GridMate::ConnectionID,
|
||||
// GridMate::CarrierDisconnectReason)
|
||||
//{
|
||||
// m_lastSecondStats.clear();
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnConnectionEstablished (GridMate::Carrier*, GridMate::ConnectionID)
|
||||
//{
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnDisconnect (GridMate::Carrier*,
|
||||
// GridMate::ConnectionID,
|
||||
// GridMate::CarrierDisconnectReason)
|
||||
//{
|
||||
// /*
|
||||
// * CarrierDrillerBus doesn't provide enough information to correctly keep track of network traffic for all peers.
|
||||
// * This is a work around until that is fixed to at least not over report the bandwidth amount.
|
||||
// */
|
||||
// m_lastSecondStats.clear();
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnDriverError (GridMate::Carrier*,
|
||||
// GridMate::ConnectionID,
|
||||
// const GridMate::DriverError&)
|
||||
//{
|
||||
// m_lastSecondStats.clear();
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnSecurityError (GridMate::Carrier*,
|
||||
// GridMate::ConnectionID,
|
||||
// const GridMate::SecurityError&)
|
||||
//{
|
||||
// m_lastSecondStats.clear();
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnUpdateStatistics (const GridMate::string& address,
|
||||
// const GridMate::TrafficControl::Statistics&,
|
||||
// const GridMate::TrafficControl::Statistics&,
|
||||
// const GridMate::TrafficControl::Statistics& effectiveLastSecond,
|
||||
// const GridMate::TrafficControl::Statistics&)
|
||||
//{
|
||||
// m_lastSecondStats[address] = effectiveLastSecond;
|
||||
//}
|
||||
|
||||
//void MultiplayerDebugPerEntityReporter::OnConnectionStateChanged (GridMate::Carrier*,
|
||||
// GridMate::ConnectionID,
|
||||
// GridMate::Carrier::ConnectionStates)
|
||||
//{
|
||||
// m_lastSecondStats.clear();
|
||||
//}
|
||||
|
||||
void MultiplayerDebugPerEntityReporter::UpdateTrafficStatistics()
|
||||
{
|
||||
#if defined(IMGUI_ENABLED)
|
||||
AZ::u32 dataReceived = 0, dataSent = 0;
|
||||
|
||||
for (auto& perConnection : m_lastSecondStats)
|
||||
{
|
||||
dataReceived += perConnection.second.m_dataReceived;
|
||||
dataSent += perConnection.second.m_dataSend;
|
||||
}
|
||||
|
||||
if (dataReceived !=0 || dataSent != 0)
|
||||
{
|
||||
ImGui::Text("Total bandwidth: Sent %u kbps Received %u kbps.", dataSent * 8 / 1000, dataReceived * 8 / 1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Total bandwidth: Sent -- kbps Received -- kbps.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void MultiplayerDebugPerEntityReporter::OnImGuiUpdate()
|
||||
{
|
||||
#if defined(IMGUI_ENABLED)
|
||||
if (ImGui::BeginMainMenuBar())
|
||||
static ImGuiTextFilter filter;
|
||||
filter.Draw();
|
||||
|
||||
if (ImGui::CollapsingHeader("Receiving Entities"))
|
||||
{
|
||||
if (ImGui::BeginMenu("GridMate"))
|
||||
for (auto& entityPair : m_receivingEntityReports)
|
||||
{
|
||||
if (m_showServerReportWindow)
|
||||
if (!filter.PassFilter(entityPair.first.c_str()))
|
||||
{
|
||||
if (ImGui::MenuItem("Hide Multiplayer Analytics Window"))
|
||||
{
|
||||
m_showServerReportWindow = false;
|
||||
}
|
||||
}
|
||||
else if (ImGui::MenuItem("Show Multiplayer Analytics Window"))
|
||||
{
|
||||
m_showServerReportWindow = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
ImGui::Separator();
|
||||
if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk))
|
||||
{
|
||||
DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
|
||||
if (m_showServerReportWindow)
|
||||
if (ImGui::CollapsingHeader("Sending Entities"))
|
||||
{
|
||||
if (ImGui::Begin("Multiplayer Analytics", &m_showServerReportWindow))
|
||||
for (auto& entityPair : m_sendingEntityReports)
|
||||
{
|
||||
// General carrier stats
|
||||
UpdateTrafficStatistics();
|
||||
|
||||
if (ImGui::Checkbox("Analyze network traffic", &m_isTrackingMessages))
|
||||
if (!filter.PassFilter(entityPair.first.c_str()))
|
||||
{
|
||||
if (m_isTrackingMessages)
|
||||
{
|
||||
//GridMate::Debug::ReplicaDrillerBus::Handler::BusConnect();
|
||||
}
|
||||
else
|
||||
{
|
||||
//GridMate::Debug::ReplicaDrillerBus::Handler::BusDisconnect();
|
||||
|
||||
m_currentReceivingEntityReport.Reset();
|
||||
m_receivingEntityReports.clear();
|
||||
|
||||
m_currentSendingEntityReport.Reset();
|
||||
m_sendingEntityReports.clear();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m_isTrackingMessages)
|
||||
ImGui::Separator();
|
||||
if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk))
|
||||
{
|
||||
ImGui::Separator();
|
||||
|
||||
static ImGuiTextFilter filter;
|
||||
filter.Draw();
|
||||
|
||||
if (ImGui::CollapsingHeader("Received replicas per type"))
|
||||
{
|
||||
for (auto& entityPair : m_receivingEntityReports)
|
||||
{
|
||||
if (!filter.PassFilter(entityPair.first.c_str()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk))
|
||||
{
|
||||
DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("Sent replicas per type"))
|
||||
{
|
||||
for (auto& entityPair : m_sendingEntityReports)
|
||||
{
|
||||
if (!filter.PassFilter(entityPair.first.c_str()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ReplicatedStateTreeNode(entityPair.first, entityPair.second, k_ImGuiDusk))
|
||||
{
|
||||
DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
}
|
||||
DisplayReplicatedStateReport(entityPair.second.GetComponentReports(), m_replicatedStateKbpsWarn, m_replicatedStateMaxSizeWarn);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName)
|
||||
void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStart(AzNetworking::SerializerMode mode,
|
||||
[[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] const char* entityName)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case AzNetworking::SerializerMode::ReadFromObject:
|
||||
m_currentSendingEntityReport.Reset();
|
||||
break;
|
||||
case AzNetworking::SerializerMode::WriteToObject:
|
||||
m_currentReceivingEntityReport.Reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName)
|
||||
void MultiplayerDebugPerEntityReporter::RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, [[maybe_unused]] Multiplayer::NetComponentId netComponentId)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case AzNetworking::SerializerMode::ReadFromObject:
|
||||
m_currentSendingEntityReport.ReportFragmentEnd();
|
||||
break;
|
||||
case AzNetworking::SerializerMode::WriteToObject:
|
||||
m_currentReceivingEntityReport.ReportFragmentEnd();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerDebugPerEntityReporter::RecordEntitySerializeStop(AzNetworking::SerializerMode mode,
|
||||
[[maybe_unused]] AZ::EntityId entityId, const char* entityName)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case AzNetworking::SerializerMode::ReadFromObject:
|
||||
m_sendingEntityReports[entityName].Combine(m_currentSendingEntityReport);
|
||||
break;
|
||||
case AzNetworking::SerializerMode::WriteToObject:
|
||||
m_receivingEntityReports[entityName].Combine(m_currentReceivingEntityReport);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerDebugPerEntityReporter::RecordPropertySent(
|
||||
AZ::EntityId entityId,
|
||||
Multiplayer::NetComponentId netComponentId,
|
||||
Multiplayer::PropertyIndex propertyId,
|
||||
uint32_t totalBytes)
|
||||
{
|
||||
// TODO
|
||||
if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry())
|
||||
{
|
||||
m_currentSendingEntityReport.ReportField(static_cast<AZ::u32>(netComponentId),
|
||||
componentRegistry->GetComponentName(netComponentId),
|
||||
componentRegistry->GetComponentPropertyName(netComponentId, propertyId), totalBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerDebugPerEntityReporter::RecordPropertyReceived(
|
||||
@@ -403,11 +214,21 @@ namespace MultiplayerDiagnostics
|
||||
Multiplayer::PropertyIndex propertyId,
|
||||
uint32_t totalBytes)
|
||||
{
|
||||
if (Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry())
|
||||
if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry())
|
||||
{
|
||||
m_currentReceivingEntityReport.ReportField(static_cast<AZ::u32>(netComponentId),
|
||||
componentRegistry->GetComponentName(netComponentId),
|
||||
componentRegistry->GetComponentPropertyName(netComponentId, propertyId), totalBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerDebugPerEntityReporter::RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes)
|
||||
{
|
||||
if (const Multiplayer::MultiplayerComponentRegistry* componentRegistry = Multiplayer::GetMultiplayerComponentRegistry())
|
||||
{
|
||||
m_currentSendingEntityReport.ReportField(static_cast<AZ::u32>(netComponentId),
|
||||
componentRegistry->GetComponentName(netComponentId),
|
||||
componentRegistry->GetComponentRpcName(netComponentId, rpcId), totalBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <GridMate/Drillers/ReplicaDriller.h>
|
||||
#include "MultiplayerDebugByteReporter.h"
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
@@ -22,66 +21,27 @@ namespace MultiplayerDiagnostics
|
||||
* \brief GridMate network live analysis tool via ImGui.
|
||||
*/
|
||||
class MultiplayerDebugPerEntityReporter
|
||||
: public AZ::Interface<MultilayerIPerEntityStats>::Registrar
|
||||
: public AZ::Interface<MultiplayerIPerEntityStats>::Registrar
|
||||
{
|
||||
public:
|
||||
MultiplayerDebugPerEntityReporter();
|
||||
~MultiplayerDebugPerEntityReporter() override;
|
||||
MultiplayerDebugPerEntityReporter() = default;
|
||||
~MultiplayerDebugPerEntityReporter() override = default;
|
||||
|
||||
// main update loop
|
||||
void OnImGuiUpdate();
|
||||
|
||||
//! MultilayerIPerEntityStats
|
||||
// @{
|
||||
void RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName);
|
||||
void RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName);
|
||||
void RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) override;
|
||||
void RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, Multiplayer::NetComponentId netComponentId) override;
|
||||
void RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName) override;
|
||||
void RecordPropertySent(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override;
|
||||
void RecordPropertyReceived(Multiplayer::NetComponentId netComponentId, Multiplayer::PropertyIndex propertyId, uint32_t totalBytes) override;
|
||||
void RecordRpcSent(Multiplayer::NetComponentId netComponentId, Multiplayer::RpcIndex rpcId, uint32_t totalBytes) override;
|
||||
// }@
|
||||
|
||||
/*void OnReceiveReplicaBegin(AZ::EntityId entityId, const void* data, size_t len) override;
|
||||
void OnReceiveReplicaEnd(AZ::EntityId entityId) override;
|
||||
void OnReceiveReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex) override;
|
||||
void OnReceiveDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::DataSetBase* dataSet, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override;
|
||||
void OnReceiveRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override;*/
|
||||
|
||||
// ReplicaDrillerBus - sending
|
||||
|
||||
/*void OnSendReplicaBegin(AZ::EntityId entityId) override;
|
||||
void OnSendReplicaEnd(AZ::EntityId entityId, const void* data, size_t len) override;
|
||||
void OnSendReplicaChunkEnd(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, const void* data, size_t len) override;
|
||||
void OnSendDataSet(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::DataSetBase* dataSet, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override;
|
||||
void OnSendRpc(GridMate::ReplicaChunkBase* chunk, AZ::u32 chunkIndex, GridMate::Internal::RpcRequest* rpc, GridMate::PeerId from, GridMate::PeerId to, const void* data, size_t len) override;*/
|
||||
|
||||
//// CarrierDrillerBus
|
||||
//void OnIncomingConnection (GridMate::Carrier* carrier, GridMate::ConnectionID id) override;
|
||||
//void OnFailedToConnect (GridMate::Carrier* carrier,
|
||||
// GridMate::ConnectionID id,
|
||||
// GridMate::CarrierDisconnectReason reason) override;
|
||||
//void OnConnectionEstablished (GridMate::Carrier* carrier, GridMate::ConnectionID id) override;
|
||||
//void OnDisconnect (GridMate::Carrier* carrier,
|
||||
// GridMate::ConnectionID id,
|
||||
// GridMate::CarrierDisconnectReason reason) override;
|
||||
//void OnDriverError (GridMate::Carrier* carrier,
|
||||
// GridMate::ConnectionID id,
|
||||
// const GridMate::DriverError& error) override;
|
||||
//void OnSecurityError (GridMate::Carrier* carrier,
|
||||
// GridMate::ConnectionID id,
|
||||
// const GridMate::SecurityError& error) override;
|
||||
//void OnUpdateStatistics (const GridMate::string& address,
|
||||
// const GridMate::TrafficControl::Statistics& lastSecond,
|
||||
// const GridMate::TrafficControl::Statistics& lifeTime,
|
||||
// const GridMate::TrafficControl::Statistics& effectiveLastSecond,
|
||||
// const GridMate::TrafficControl::Statistics& effectiveLifeTime) override;
|
||||
//void OnConnectionStateChanged (GridMate::Carrier* carrier,
|
||||
// GridMate::ConnectionID id,
|
||||
// GridMate::Carrier::ConnectionStates newState) override;
|
||||
|
||||
private:
|
||||
|
||||
bool m_showServerReportWindow = false;
|
||||
bool m_isTrackingMessages = false;
|
||||
|
||||
AZStd::map<AZStd::string, EntityReporter> m_sendingEntityReports{};
|
||||
EntityReporter m_currentSendingEntityReport;
|
||||
|
||||
@@ -90,8 +50,5 @@ namespace MultiplayerDiagnostics
|
||||
|
||||
float m_replicatedStateKbpsWarn = 10.f;
|
||||
float m_replicatedStateMaxSizeWarn = 30.f;
|
||||
|
||||
void UpdateTrafficStatistics();
|
||||
AZStd::map<GridMate::string, GridMate::TrafficControl::Statistics> m_lastSecondStats;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include <AzNetworking/Framework/INetworkInterface.h>
|
||||
#include <Multiplayer/IMultiplayer.h>
|
||||
|
||||
#pragma optimize("", off)
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
void MultiplayerDebugSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
@@ -65,6 +67,7 @@ namespace Multiplayer
|
||||
{
|
||||
ImGui::Checkbox("Networking Stats", &m_displayNetworkingStats);
|
||||
ImGui::Checkbox("Multiplayer Stats", &m_displayMultiplayerStats);
|
||||
ImGui::Checkbox("Multiplayer Per Entity Stats", &m_displayPerEntityStats);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
@@ -324,10 +327,15 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_reporter)
|
||||
if (m_displayPerEntityStats)
|
||||
{
|
||||
m_reporter->OnImGuiUpdate();
|
||||
if (ImGui::Begin("Multiplayer Per Entity Analytics", &m_displayPerEntityStats))
|
||||
{
|
||||
if (m_reporter)
|
||||
{
|
||||
m_reporter->OnImGuiUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace Multiplayer
|
||||
private:
|
||||
bool m_displayNetworkingStats = false;
|
||||
bool m_displayMultiplayerStats = false;
|
||||
bool m_displayPerEntityStats = false;
|
||||
|
||||
AZStd::unique_ptr<MultiplayerDiagnostics::MultiplayerDebugPerEntityReporter> m_reporter;
|
||||
};
|
||||
|
||||
@@ -30,25 +30,33 @@ namespace Multiplayer
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv.resize(rpcCount);
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordEntitySerializeStart(AZ::EntityId entityId, const char* entityName)
|
||||
void MultiplayerStats::RecordEntitySerializeStart(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName)
|
||||
{
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultilayerIPerEntityStats>::Get())
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultiplayerIPerEntityStats>::Get())
|
||||
{
|
||||
perEntityStats->RecordEntitySerializeStart(entityId, entityName);
|
||||
perEntityStats->RecordEntitySerializeStart(mode, entityId, entityName);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordEntitySerializeStop(AZ::EntityId entityId, const char* entityName)
|
||||
void MultiplayerStats::RecordComponentSerializeEnd(AzNetworking::SerializerMode mode, NetComponentId netComponentId)
|
||||
{
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultilayerIPerEntityStats>::Get())
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultiplayerIPerEntityStats>::Get())
|
||||
{
|
||||
perEntityStats->RecordEntitySerializeStop(entityId, entityName);
|
||||
perEntityStats->RecordComponentSerializeEnd(mode, netComponentId);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordEntitySerializeStop(AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName)
|
||||
{
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultiplayerIPerEntityStats>::Get())
|
||||
{
|
||||
perEntityStats->RecordEntitySerializeStop(mode, entityId, entityName);
|
||||
}
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes)
|
||||
{
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultilayerIPerEntityStats>::Get())
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultiplayerIPerEntityStats>::Get())
|
||||
{
|
||||
perEntityStats->RecordPropertySent(netComponentId, propertyId, totalBytes);
|
||||
}
|
||||
@@ -63,7 +71,7 @@ namespace Multiplayer
|
||||
|
||||
void MultiplayerStats::RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes)
|
||||
{
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultilayerIPerEntityStats>::Get())
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultiplayerIPerEntityStats>::Get())
|
||||
{
|
||||
perEntityStats->RecordPropertyReceived(netComponentId, propertyId, totalBytes);
|
||||
}
|
||||
@@ -78,6 +86,11 @@ namespace Multiplayer
|
||||
|
||||
void MultiplayerStats::RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes)
|
||||
{
|
||||
if (auto* perEntityStats = AZ::Interface<MultiplayerDiagnostics::MultiplayerIPerEntityStats>::Get())
|
||||
{
|
||||
perEntityStats->RecordRpcSent(netComponentId, rpcId, totalBytes);
|
||||
}
|
||||
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
const uint16_t rpcIndex = aznumeric_cast<uint16_t>(rpcId);
|
||||
m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_totalCalls++;
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
#include <AzFramework/Components/TransformComponent.h>
|
||||
|
||||
#pragma optimize("", off)
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
EntityReplicator::EntityReplicator
|
||||
@@ -441,7 +443,12 @@ namespace Multiplayer
|
||||
{
|
||||
// Received rpc metrics, log rpc sent, number of bytes, and the componentId/rpcId for bandwidth metrics
|
||||
MultiplayerStats& stats = GetMultiplayer()->GetStats();
|
||||
stats.RecordEntitySerializeStart(AzNetworking::SerializerMode::ReadFromObject,
|
||||
GetEntityHandle().GetEntity()->GetId(), GetEntityHandle().GetEntity()->GetName().c_str());
|
||||
stats.RecordRpcSent(entityRpcMessage.GetComponentId(), entityRpcMessage.GetRpcIndex(), entityRpcMessage.GetEstimatedSerializeSize());
|
||||
stats.RecordComponentSerializeEnd(AzNetworking::SerializerMode::ReadFromObject, entityRpcMessage.GetComponentId());
|
||||
stats.RecordEntitySerializeStop(AzNetworking::SerializerMode::ReadFromObject,
|
||||
GetEntityHandle().GetEntity()->GetId(), GetEntityHandle().GetEntity()->GetName().c_str());
|
||||
|
||||
m_replicationManager.AddDeferredRpcMessage(entityRpcMessage);
|
||||
}
|
||||
@@ -515,7 +522,7 @@ namespace Multiplayer
|
||||
&& (GetRemoteNetworkRole() == NetEntityRole::Server))
|
||||
{
|
||||
// We are on a server, and we received this message from another server, therefore we should forward this to our autonomous player
|
||||
// This can occur if we've recently migrated
|
||||
// This can occur if we've recently migrated
|
||||
result = RpcValidationResult::ForwardToAutonomous;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user