Initial work on multiple gem multiplayer components
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzNetworking/ConnectionLayer/IConnection.h>
|
||||
#include <AzNetworking/DataStructures/ByteBuffer.h>
|
||||
#include <Include/MultiplayerStats.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
@@ -23,21 +24,6 @@ namespace AzNetworking
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
struct MultiplayerStats
|
||||
{
|
||||
uint64_t m_entityCount = 0;
|
||||
uint64_t m_clientConnectionCount = 0;
|
||||
uint64_t m_serverConnectionCount = 0;
|
||||
uint64_t m_propertyUpdatesSent = 0;
|
||||
uint64_t m_propertyUpdatesSentBytes = 0;
|
||||
uint64_t m_propertyUpdatesRecv = 0;
|
||||
uint64_t m_propertyUpdatesRecvBytes = 0;
|
||||
uint64_t m_rpcsSent = 0;
|
||||
uint64_t m_rpcsSentBytes = 0;
|
||||
uint64_t m_rpcsRecv = 0;
|
||||
uint64_t m_rpcsRecvBytes = 0;
|
||||
};
|
||||
|
||||
//! Collection of types of Multiplayer Connections
|
||||
enum class MultiplayerAgentType
|
||||
{
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Include/MultiplayerStats.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
void MultiplayerStats::ReserveComponentStats(uint16_t netComponentId, uint16_t propertyCount, uint16_t rpcCount)
|
||||
{
|
||||
if (m_componentStats.size() <= netComponentId)
|
||||
{
|
||||
m_componentStats.resize(netComponentId + 1);
|
||||
}
|
||||
m_componentStats[netComponentId].m_propertyUpdatesSent.resize(propertyCount);
|
||||
m_componentStats[netComponentId].m_propertyUpdatesRecv.resize(propertyCount);
|
||||
m_componentStats[netComponentId].m_rpcsSent.resize(rpcCount);
|
||||
m_componentStats[netComponentId].m_rpcsRecv.resize(rpcCount);
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordPropertySent(uint16_t netComponentId, uint16_t propertyId, uint32_t totalBytes)
|
||||
{
|
||||
m_componentStats[netComponentId].m_propertyUpdatesSent[propertyId].m_totalCalls++;
|
||||
m_componentStats[netComponentId].m_propertyUpdatesSent[propertyId].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentId].m_propertyUpdatesSent[propertyId].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentId].m_propertyUpdatesSent[propertyId].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordPropertyReceived(uint16_t netComponentId, uint16_t propertyId, uint32_t totalBytes)
|
||||
{
|
||||
m_componentStats[netComponentId].m_propertyUpdatesRecv[propertyId].m_totalCalls++;
|
||||
m_componentStats[netComponentId].m_propertyUpdatesRecv[propertyId].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentId].m_propertyUpdatesRecv[propertyId].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentId].m_propertyUpdatesRecv[propertyId].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordRpcSent(uint16_t netComponentId, uint16_t rpcId, uint32_t totalBytes)
|
||||
{
|
||||
m_componentStats[netComponentId].m_rpcsSent[rpcId].m_totalCalls++;
|
||||
m_componentStats[netComponentId].m_rpcsSent[rpcId].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentId].m_rpcsSent[rpcId].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentId].m_rpcsSent[rpcId].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordRpcReceived(uint16_t netComponentId, uint16_t rpcId, uint32_t totalBytes)
|
||||
{
|
||||
m_componentStats[netComponentId].m_rpcsRecv[rpcId].m_totalCalls++;
|
||||
m_componentStats[netComponentId].m_rpcsRecv[rpcId].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentId].m_rpcsRecv[rpcId].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentId].m_rpcsRecv[rpcId].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::TickStats(AZ::TimeMs metricFrameTimeMs)
|
||||
{
|
||||
m_totalHistoryTimeMs = metricFrameTimeMs * static_cast<AZ::TimeMs>(RingbufferSamples);
|
||||
m_recordMetricIndex = ++m_recordMetricIndex % RingbufferSamples;
|
||||
}
|
||||
|
||||
static void CombineMetrics(MultiplayerStats::Metric& outArg1, const MultiplayerStats::Metric& arg2)
|
||||
{
|
||||
outArg1.m_totalCalls += arg2.m_totalCalls;
|
||||
outArg1.m_totalBytes += arg2.m_totalBytes;
|
||||
for (uint32_t index = 0; index < MultiplayerStats::RingbufferSamples; ++index)
|
||||
{
|
||||
outArg1.m_callHistory[index] += arg2.m_callHistory[index];
|
||||
outArg1.m_byteHistory[index] += arg2.m_byteHistory[index];
|
||||
}
|
||||
}
|
||||
|
||||
static MultiplayerStats::Metric SumMetricVector(const AZStd::vector<MultiplayerStats::Metric>& metricVector)
|
||||
{
|
||||
MultiplayerStats::Metric result;
|
||||
for (AZStd::size_t index = 0; index < metricVector.size(); ++index)
|
||||
{
|
||||
CombineMetrics(result, metricVector[index]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentPropertyUpdateSentMetrics(uint16_t netComponentId) const
|
||||
{
|
||||
return SumMetricVector(m_componentStats[netComponentId].m_propertyUpdatesSent);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentPropertyUpdateRecvMetrics(uint16_t netComponentId) const
|
||||
{
|
||||
return SumMetricVector(m_componentStats[netComponentId].m_propertyUpdatesRecv);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsSentMetrics(uint16_t netComponentId) const
|
||||
{
|
||||
return SumMetricVector(m_componentStats[netComponentId].m_rpcsSent);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsRecvMetrics(uint16_t netComponentId) const
|
||||
{
|
||||
return SumMetricVector(m_componentStats[netComponentId].m_rpcsRecv);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalPropertyUpdateSentMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
CombineMetrics(result, CalculateComponentPropertyUpdateSentMetrics(index));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalPropertyUpdateRecvMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
CombineMetrics(result, CalculateComponentPropertyUpdateRecvMetrics(index));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalRpcsSentMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
CombineMetrics(result, CalculateComponentRpcsSentMetrics(index));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalRpcsRecvMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
CombineMetrics(result, CalculateComponentRpcsRecvMetrics(index));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Time/ITime.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/containers/fixed_vector.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
class INetworkInterface;
|
||||
}
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
struct MultiplayerStats
|
||||
{
|
||||
uint64_t m_entityCount = 0;
|
||||
uint64_t m_clientConnectionCount = 0;
|
||||
uint64_t m_serverConnectionCount = 0;
|
||||
|
||||
uint64_t m_recordMetricIndex = 0;
|
||||
AZ::TimeMs m_totalHistoryTimeMs = AZ::TimeMs{ 0 };
|
||||
|
||||
static const uint32_t RingbufferSamples = 32;
|
||||
using MetricRingbuffer = AZStd::fixed_vector<uint64_t, RingbufferSamples>;
|
||||
struct Metric
|
||||
{
|
||||
uint64_t m_totalCalls = 0;
|
||||
uint64_t m_totalBytes = 0;
|
||||
MetricRingbuffer m_callHistory;
|
||||
MetricRingbuffer m_byteHistory;
|
||||
};
|
||||
|
||||
struct ComponentStats
|
||||
{
|
||||
AZStd::vector<Metric> m_propertyUpdatesSent;
|
||||
AZStd::vector<Metric> m_propertyUpdatesRecv;
|
||||
AZStd::vector<Metric> m_rpcsSent;
|
||||
AZStd::vector<Metric> m_rpcsRecv;
|
||||
};
|
||||
AZStd::vector<ComponentStats> m_componentStats;
|
||||
|
||||
void ReserveComponentStats(uint16_t netComponentId, uint16_t propertyCount, uint16_t rpcCount);
|
||||
void RecordPropertySent(uint16_t netComponentId, uint16_t propertyId, uint32_t totalBytes);
|
||||
void RecordPropertyReceived(uint16_t netComponentId, uint16_t propertyId, uint32_t totalBytes);
|
||||
void RecordRpcSent(uint16_t netComponentId, uint16_t rpcId, uint32_t totalBytes);
|
||||
void RecordRpcReceived(uint16_t netComponentId, uint16_t rpcId, uint32_t totalBytes);
|
||||
void TickStats(AZ::TimeMs metricFrameTimeMs);
|
||||
|
||||
Metric CalculateComponentPropertyUpdateSentMetrics(uint16_t netComponentId) const;
|
||||
Metric CalculateComponentPropertyUpdateRecvMetrics(uint16_t netComponentId) const;
|
||||
Metric CalculateComponentRpcsSentMetrics(uint16_t netComponentId) const;
|
||||
Metric CalculateComponentRpcsRecvMetrics(uint16_t netComponentId) const;
|
||||
Metric CalculateTotalPropertyUpdateSentMetrics() const;
|
||||
Metric CalculateTotalPropertyUpdateRecvMetrics() const;
|
||||
Metric CalculateTotalRpcsSentMetrics() const;
|
||||
Metric CalculateTotalRpcsRecvMetrics() const;
|
||||
};
|
||||
}
|
||||
@@ -22,12 +22,16 @@ namespace {{ Namespace }}
|
||||
void RegisterMultiplayerComponents()
|
||||
{
|
||||
Multiplayer::MultiplayerComponentRegistry* multiplayerComponentRegistry = GetMultiplayerComponentRegistry();
|
||||
Multiplayer::MultiplayerStats& stats = AZ::Interface<Multiplayer::IMultiplayer>::Get()->GetStats();
|
||||
{% for Component in dataFiles %}
|
||||
{% set ComponentName = Component.attrib['Name'] %}
|
||||
{% set ComponentBaseName = ComponentName %}
|
||||
{% if Component.attrib['OverrideComponent']|booleanTrue %}
|
||||
{% set ComponentBaseName = ComponentName + "Base" %}
|
||||
{% endif %}
|
||||
{% set ComponentName = Component.attrib['Name'] %}
|
||||
{% set ComponentBaseName = ComponentName %}
|
||||
{% if Component.attrib['OverrideComponent']|booleanTrue %}
|
||||
{% set ComponentBaseName = ComponentName + "Base" %}
|
||||
{% endif %}
|
||||
{% set NetworkInputCount = Component.findall('NetworkInput') | len %}
|
||||
{% set NetworkPropertyCount = Component.findall('NetworkProperty') | len %}
|
||||
{% set RpcCount = Component.findall('RemoteProcedure') | len %}
|
||||
{
|
||||
Multiplayer::MultiplayerComponentRegistry::ComponentData componentData;
|
||||
componentData.m_gemName = AZ::Name("{{ Namespace }}");
|
||||
@@ -35,6 +39,7 @@ namespace {{ Namespace }}
|
||||
componentData.m_componentPropertyNameLookupFunction = {{ ComponentBaseName }}::GetNetworkPropertyName;
|
||||
componentData.m_componentRpcNameLookupFunction = {{ ComponentBaseName }}::GetRpcName;
|
||||
{{ ComponentBaseName }}::s_netComponentId = multiplayerComponentRegistry->RegisterMultiplayerComponent(componentData);
|
||||
stats.ReserveComponentStats(static_cast<uint16_t>({{ ComponentBaseName }}::s_netComponentId), static_cast<uint16_t>({{ NetworkPropertyCount }}), static_cast<uint16_t>({{ RpcCount }}));
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
@@ -508,7 +508,8 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re
|
||||
static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }}),
|
||||
m_{{ LowerFirst(Property.attrib['Name']) }},
|
||||
"{{ Property.attrib['Name'] }}",
|
||||
GetNetComponentId(),
|
||||
static_cast<uint16_t>(GetNetComponentId()),
|
||||
static_cast<uint16_t>({{ UpperFirst(Component.attrib['Name']) }}Internal::NetworkProperties::{{ UpperFirst(Property.attrib['Name']) }}),
|
||||
stats
|
||||
);
|
||||
{% endif %}
|
||||
@@ -646,6 +647,16 @@ enum class RemoteProcedure
|
||||
MAX
|
||||
};
|
||||
|
||||
{% endmacro %}
|
||||
{% macro DeclareNetworkPropertyEnumerations(Component) %}
|
||||
enum class NetworkProperties
|
||||
{
|
||||
{% for NetworkProperty in Component.iter('NetworkProperty') %}
|
||||
{{ UpperFirst(NetworkProperty.attrib['Name']) }},
|
||||
{% endfor %}
|
||||
MAX
|
||||
};
|
||||
|
||||
{% endmacro %}
|
||||
{#
|
||||
|
||||
@@ -881,6 +892,9 @@ m_{{ LowerFirst(Property.attrib['Name']) }} = m_{{ LowerFirst(Property.attrib['N
|
||||
{% else %}
|
||||
{% set ControllerBaseName = ControllerName %}
|
||||
{% endif %}
|
||||
{% set NetworkInputCount = Component.findall('NetworkInput') | len %}
|
||||
{% set NetworkPropertyCount = Component.findall('NetworkProperty') | len %}
|
||||
{% set RpcCount = Component.findall('RemoteProcedure') | len %}
|
||||
#include "{{ includeFile }}"
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Console/ILogger.h>
|
||||
@@ -906,6 +920,7 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
namespace {{ UpperFirst(Component.attrib['Name']) }}Internal
|
||||
{
|
||||
{{ DeclareRemoteProcedureEnumerations(Component)|indent(8) }}
|
||||
{{ DeclareNetworkPropertyEnumerations(Component)|indent(8) }}
|
||||
{{ DefineNetworkPropertyDirtyEnumeration(Component, ClassType, 'Authority', 'Authority')|indent(8) }}
|
||||
{{ DefineNetworkPropertyDirtyEnumeration(Component, ClassType, 'Authority', 'Client')|indent(8) }}
|
||||
{{ DefineNetworkPropertyDirtyEnumeration(Component, ClassType, 'Authority', 'Server')|indent(8) }}
|
||||
@@ -1383,12 +1398,32 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
{% endif %}
|
||||
const char* {{ ComponentBaseName }}::GetNetworkPropertyName([[maybe_unused]] uint16_t propertyIndex)
|
||||
{
|
||||
return "";
|
||||
{% if NetworkPropertyCount > 0 %}
|
||||
const {{ UpperFirst(Component.attrib['Name']) }}Internal::NetworkProperties propertyId = static_cast<{{ UpperFirst(Component.attrib['Name']) }}Internal::NetworkProperties>(propertyIndex);
|
||||
switch (propertyId)
|
||||
{
|
||||
{% for NetworkProperty in Component.iter('NetworkProperty') %}
|
||||
case {{ UpperFirst(Component.attrib['Name']) }}Internal::NetworkProperties::{{ UpperFirst(NetworkProperty.attrib['Name']) }}:
|
||||
return "{{ UpperFirst(NetworkProperty.attrib['Name']) }}";
|
||||
{% endfor %}
|
||||
}
|
||||
{% endif %}
|
||||
return "Unknown network property";
|
||||
}
|
||||
|
||||
const char* {{ ComponentBaseName }}::GetRpcName([[maybe_unused]] uint16_t rpcIndex)
|
||||
{
|
||||
return "";
|
||||
{% if RpcCount > 0 %}
|
||||
const {{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure rpcId = static_cast<{{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure>(rpcIndex);
|
||||
switch (rpcId)
|
||||
{
|
||||
{% for RemoteProcedure in Component.iter('RemoteProcedure') %}
|
||||
case {{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ RemoteProcedure.attrib['Name'] }}:
|
||||
return "{{ RemoteProcedure.attrib['Name'] }}";
|
||||
{% endfor %}
|
||||
}
|
||||
{% endif %}
|
||||
return "Unknown Rpc";
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
@@ -104,13 +104,14 @@ namespace Multiplayer
|
||||
template <typename TYPE>
|
||||
inline void SerializeNetworkPropertyHelper
|
||||
(
|
||||
AzNetworking::ISerializer& serializer,
|
||||
bool modifyRecord,
|
||||
AzNetworking::FixedSizeBitsetView& bitset,
|
||||
int32_t bitIndex,
|
||||
TYPE& value,
|
||||
const char* name,
|
||||
[[maybe_unused]] NetComponentId componentId,
|
||||
AzNetworking::ISerializer& serializer,
|
||||
bool modifyRecord,
|
||||
AzNetworking::FixedSizeBitsetView& bitset,
|
||||
int32_t bitIndex,
|
||||
TYPE& value,
|
||||
const char* name,
|
||||
uint16_t componentId,
|
||||
uint16_t propertyId,
|
||||
MultiplayerStats& stats
|
||||
)
|
||||
{
|
||||
@@ -131,13 +132,11 @@ namespace Multiplayer
|
||||
{
|
||||
if (modifyRecord)
|
||||
{
|
||||
stats.m_propertyUpdatesRecv++;
|
||||
stats.m_propertyUpdatesRecvBytes += updateSize;
|
||||
stats.RecordPropertyReceived(componentId, propertyId, updateSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
stats.m_propertyUpdatesSent++;
|
||||
stats.m_propertyUpdatesSentBytes += updateSize;
|
||||
stats.RecordPropertySent(componentId, propertyId, updateSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,26 +95,72 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
void ComputePerSecondValues(const MultiplayerStats& stats, const MultiplayerStats::Metric& metric, float& outCallsPerSecond, float& outBytesPerSecond)
|
||||
{
|
||||
uint64_t summedCalls = 0;
|
||||
uint64_t summedBytes = 0;
|
||||
for (uint32_t index = 0; index < MultiplayerStats::RingbufferSamples; ++index)
|
||||
{
|
||||
summedCalls += metric.m_callHistory[index];
|
||||
summedBytes += metric.m_byteHistory[index];
|
||||
}
|
||||
const float totalTimeSeconds = static_cast<float>(stats.m_totalHistoryTimeMs) / 1000.0f;
|
||||
outCallsPerSecond = static_cast<float>(summedCalls) / totalTimeSeconds;
|
||||
outBytesPerSecond = static_cast<float>(summedBytes) / totalTimeSeconds;
|
||||
}
|
||||
|
||||
void DrawMetricTitle(const ImVec4& entryColour)
|
||||
{
|
||||
ImGui::Columns(6);
|
||||
|
||||
ImGui::TextColored(entryColour, "Name"); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "Category"); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "Total Calls"); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "Total Bytes"); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "Calls/Sec"); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "Bytes/Sec"); ImGui::NextColumn();
|
||||
}
|
||||
|
||||
void DrawMetricRow(const char* name, const char* category, const ImVec4& entryColour, const MultiplayerStats& stats, const MultiplayerStats::Metric& metric)
|
||||
{
|
||||
float callsPerSecond = 0.0f;
|
||||
float bytesPerSecond = 0.0f;
|
||||
ComputePerSecondValues(stats, metric, callsPerSecond, bytesPerSecond);
|
||||
|
||||
ImGui::TextColored(entryColour, "%s", name); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "%s", category); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "%10llu", aznumeric_cast<AZ::u64>(metric.m_totalCalls)); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "%10llu", aznumeric_cast<AZ::u64>(metric.m_totalBytes)); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "%10.2f", callsPerSecond); ImGui::NextColumn();
|
||||
ImGui::TextColored(entryColour, "%10.2f", bytesPerSecond); ImGui::NextColumn();
|
||||
}
|
||||
|
||||
void MultiplayerDebugSystemComponent::OnImGuiUpdate()
|
||||
{
|
||||
const ImVec4 titleColour = ImColor(1.00f, 0.80f, 0.12f);
|
||||
const ImVec4 entryColour = ImColor(0.32f, 1.00f, 1.00f);
|
||||
|
||||
if (m_displayStats)
|
||||
{
|
||||
if (ImGui::Begin("Multiplayer Stats", &m_displayStats, ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
IMultiplayer* multiplayer = AZ::Interface<IMultiplayer>::Get();
|
||||
Multiplayer::MultiplayerStats& stats = multiplayer->GetStats();
|
||||
const Multiplayer::MultiplayerStats& stats = multiplayer->GetStats();
|
||||
ImGui::Text("Multiplayer operating in %s mode", GetEnumString(multiplayer->GetAgentType()));
|
||||
ImGui::Text("Total networked entities: %llu", aznumeric_cast<AZ::u64>(stats.m_entityCount));
|
||||
ImGui::Text("Total client connections: %llu", aznumeric_cast<AZ::u64>(stats.m_clientConnectionCount));
|
||||
ImGui::Text("Total server connections: %llu", aznumeric_cast<AZ::u64>(stats.m_serverConnectionCount));
|
||||
ImGui::Text("Total property updates sent: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesSent));
|
||||
ImGui::Text("Total property updates sent bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesSentBytes));
|
||||
ImGui::Text("Total property updates received: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesRecv));
|
||||
ImGui::Text("Total property updates received bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesRecvBytes));
|
||||
ImGui::Text("Total RPCs sent: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsSent));
|
||||
ImGui::Text("Total RPCs sent bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsSentBytes));
|
||||
ImGui::Text("Total RPCs received: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsRecv));
|
||||
ImGui::Text("Total RPCs received bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsRecvBytes));
|
||||
|
||||
const MultiplayerStats::Metric propertyUpdatesSent = stats.CalculateTotalPropertyUpdateSentMetrics();
|
||||
const MultiplayerStats::Metric propertyUpdatesRecv = stats.CalculateTotalPropertyUpdateRecvMetrics();
|
||||
const MultiplayerStats::Metric rpcsSent = stats.CalculateTotalRpcsSentMetrics();
|
||||
const MultiplayerStats::Metric rpcsRecv = stats.CalculateTotalRpcsRecvMetrics();
|
||||
|
||||
DrawMetricTitle(titleColour);
|
||||
DrawMetricRow("Total", "PropertyUpdates Sent", entryColour, stats, propertyUpdatesSent);
|
||||
DrawMetricRow("Total", "PropertyUpdates Received", entryColour, stats, propertyUpdatesRecv);
|
||||
DrawMetricRow("Total", "Rpcs Sent", entryColour, stats, rpcsSent);
|
||||
DrawMetricRow("Total", "Rpcs Received", entryColour, stats, rpcsRecv);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
@@ -52,5 +52,7 @@ namespace Multiplayer
|
||||
#endif
|
||||
private:
|
||||
bool m_displayStats = false;
|
||||
bool m_displayPropertyStats = false;
|
||||
bool m_displayRpcStats = false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -513,14 +513,20 @@ namespace Multiplayer
|
||||
AZLOG_INFO("Total networked entities: %llu", aznumeric_cast<AZ::u64>(stats.m_entityCount));
|
||||
AZLOG_INFO("Total client connections: %llu", aznumeric_cast<AZ::u64>(stats.m_clientConnectionCount));
|
||||
AZLOG_INFO("Total server connections: %llu", aznumeric_cast<AZ::u64>(stats.m_serverConnectionCount));
|
||||
AZLOG_INFO("Total property updates sent: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesSent));
|
||||
AZLOG_INFO("Total property updates sent bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesSentBytes));
|
||||
AZLOG_INFO("Total property updates received: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesRecv));
|
||||
AZLOG_INFO("Total property updates received bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_propertyUpdatesRecvBytes));
|
||||
AZLOG_INFO("Total RPCs sent: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsSent));
|
||||
AZLOG_INFO("Total RPCs sent bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsSentBytes));
|
||||
AZLOG_INFO("Total RPCs received: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsRecv));
|
||||
AZLOG_INFO("Total RPCs received bytes: %llu", aznumeric_cast<AZ::u64>(stats.m_rpcsRecvBytes));
|
||||
|
||||
const MultiplayerStats::Metric propertyUpdatesSent = stats.CalculateTotalPropertyUpdateSentMetrics();
|
||||
const MultiplayerStats::Metric propertyUpdatesRecv = stats.CalculateTotalPropertyUpdateRecvMetrics();
|
||||
const MultiplayerStats::Metric rpcsSent = stats.CalculateTotalRpcsSentMetrics();
|
||||
const MultiplayerStats::Metric rpcsRecv = stats.CalculateTotalRpcsRecvMetrics();
|
||||
|
||||
AZLOG_INFO("Total property updates sent: %llu", aznumeric_cast<AZ::u64>(propertyUpdatesSent.m_totalCalls));
|
||||
AZLOG_INFO("Total property updates sent bytes: %llu", aznumeric_cast<AZ::u64>(propertyUpdatesSent.m_totalBytes));
|
||||
AZLOG_INFO("Total property updates received: %llu", aznumeric_cast<AZ::u64>(propertyUpdatesRecv.m_totalCalls));
|
||||
AZLOG_INFO("Total property updates received bytes: %llu", aznumeric_cast<AZ::u64>(propertyUpdatesRecv.m_totalBytes));
|
||||
AZLOG_INFO("Total RPCs sent: %llu", aznumeric_cast<AZ::u64>(rpcsSent.m_totalCalls));
|
||||
AZLOG_INFO("Total RPCs sent bytes: %llu", aznumeric_cast<AZ::u64>(rpcsSent.m_totalBytes));
|
||||
AZLOG_INFO("Total RPCs received: %llu", aznumeric_cast<AZ::u64>(rpcsRecv.m_totalCalls));
|
||||
AZLOG_INFO("Total RPCs received bytes: %llu", aznumeric_cast<AZ::u64>(rpcsRecv.m_totalBytes));
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::OnConsoleCommandInvoked
|
||||
|
||||
@@ -449,8 +449,7 @@ namespace Multiplayer
|
||||
{
|
||||
// Received rpc metrics, log rpc sent, number of bytes, and the componentId/rpcId for bandwidth metrics
|
||||
MultiplayerStats& stats = AZ::Interface<IMultiplayer>::Get()->GetStats();
|
||||
stats.m_rpcsSent++;
|
||||
stats.m_rpcsSentBytes += entityRpcMessage.GetEstimatedSerializeSize();
|
||||
stats.RecordRpcSent(static_cast<uint16_t>(entityRpcMessage.GetComponentId()), entityRpcMessage.GetRpcMessageType(), entityRpcMessage.GetEstimatedSerializeSize());
|
||||
|
||||
m_replicationManager.AddDeferredRpcMessage(entityRpcMessage);
|
||||
}
|
||||
@@ -633,8 +632,7 @@ namespace Multiplayer
|
||||
{
|
||||
// Received rpc metrics, log rpc received, time spent, number of bytes, and the componentId/rpcId for bandwidth metrics
|
||||
MultiplayerStats& stats = AZ::Interface<IMultiplayer>::Get()->GetStats();
|
||||
stats.m_rpcsRecv++;
|
||||
stats.m_rpcsRecvBytes += entityRpcMessage.GetEstimatedSerializeSize();
|
||||
stats.RecordRpcReceived(static_cast<uint16_t>(entityRpcMessage.GetComponentId()), entityRpcMessage.GetRpcMessageType(), entityRpcMessage.GetEstimatedSerializeSize());
|
||||
|
||||
if (!m_netBindComponent)
|
||||
{
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
set(FILES
|
||||
Include/IMultiplayer.h
|
||||
Include/MultiplayerStats.cpp
|
||||
Include/MultiplayerStats.h
|
||||
Source/Multiplayer_precompiled.cpp
|
||||
Source/Multiplayer_precompiled.h
|
||||
Source/MultiplayerSystemComponent.cpp
|
||||
|
||||
Reference in New Issue
Block a user