Many fixes for external gem multiplayer components and component network inputs, fixes an uninitialized variable resulting in continual desyncs, restructures our public includes to match the directory structure of source, allows autogen artefacts to be included by external gems, allowing for external multiplayer components to interact with multiplayer gem components with no extra code
This commit is contained in:
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 <Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.h>
|
||||
#include <Multiplayer/Components/NetBindComponent.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
using CorrectionEvent = AZ::Event<>;
|
||||
|
||||
class LocalPredictionPlayerInputComponent
|
||||
: public LocalPredictionPlayerInputComponentBase
|
||||
{
|
||||
public:
|
||||
AZ_MULTIPLAYER_COMPONENT(Multiplayer::LocalPredictionPlayerInputComponent, s_localPredictionPlayerInputComponentConcreteUuid, Multiplayer::LocalPredictionPlayerInputComponentBase);
|
||||
|
||||
static void Reflect([[maybe_unused]] AZ::ReflectContext* context);
|
||||
|
||||
void OnInit() override;
|
||||
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
};
|
||||
|
||||
class LocalPredictionPlayerInputComponentController
|
||||
: public LocalPredictionPlayerInputComponentControllerBase
|
||||
{
|
||||
public:
|
||||
LocalPredictionPlayerInputComponentController(LocalPredictionPlayerInputComponent& parent);
|
||||
|
||||
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
|
||||
void HandleSendClientInput
|
||||
(
|
||||
AzNetworking::IConnection* invokingConnection,
|
||||
const Multiplayer::NetworkInputArray& inputArray,
|
||||
const AZ::HashValue32& stateHash,
|
||||
const AzNetworking::PacketEncodingBuffer& clientState
|
||||
) override;
|
||||
|
||||
void HandleSendMigrateClientInput
|
||||
(
|
||||
AzNetworking::IConnection* invokingConnection,
|
||||
const Multiplayer::NetworkInputMigrationVector& inputArray
|
||||
) override;
|
||||
|
||||
void HandleSendClientInputCorrection
|
||||
(
|
||||
AzNetworking::IConnection* invokingConnection,
|
||||
const Multiplayer::ClientInputId& inputId,
|
||||
const AzNetworking::PacketEncodingBuffer& correction
|
||||
) override;
|
||||
|
||||
//! Return true if we're currently replaying inputs after a correction.
|
||||
//! If this value returns true, effects, audio, and other cosmetic triggers should be suppressed
|
||||
//! @return true if we're within correction scope and replaying inputs
|
||||
bool IsReplayingInput() const;
|
||||
|
||||
//! Return true if we're currently migrating from one host to another.
|
||||
//! @return boolean true if we're currently migrating from one host to another
|
||||
bool IsMigrating() const;
|
||||
|
||||
ClientInputId GetLastInputId() const;
|
||||
HostFrameId GetInputFrameId(const NetworkInput& input) const;
|
||||
|
||||
void CorrectionEventAddHandle(CorrectionEvent::Handler& handler);
|
||||
|
||||
private:
|
||||
|
||||
void OnMigrateStart(ClientInputId migratedInputId);
|
||||
void OnMigrateEnd();
|
||||
void UpdateAutonomous(AZ::TimeMs deltaTimeMs);
|
||||
void UpdateBankedTime(AZ::TimeMs deltaTimeMs);
|
||||
|
||||
// Implicitly sorted player input history, back() is the input that corresponds to the latest client input Id
|
||||
NetworkInputHistory m_inputHistory;
|
||||
|
||||
// Anti-cheat accumulator for clients who purposely mess with their clock rate
|
||||
NetworkInputArray m_lastInputReceived;
|
||||
|
||||
AZ::ScheduledEvent m_autonomousUpdateEvent; // Drives autonomous input collection
|
||||
AZ::ScheduledEvent m_updateBankedTimeEvent; // Drives authority bank time updates
|
||||
|
||||
CorrectionEvent m_correctionEvent;
|
||||
EntityMigrationStartEvent::Handler m_migrateStartHandler;
|
||||
EntityMigrationEndEvent::Handler m_migrateEndHandler;
|
||||
|
||||
double m_moveAccumulator = 0.0;
|
||||
double m_clientBankedTime = 0.0;
|
||||
|
||||
AZ::TimeMs m_lastInputReceivedTimeMs = AZ::TimeMs{ 0 };
|
||||
AZ::TimeMs m_lastCorrectionSentTimeMs = AZ::TimeMs{ 0 };
|
||||
|
||||
ClientInputId m_clientInputId = ClientInputId{ 0 };
|
||||
ClientInputId m_lastCorrectionInputId = ClientInputId{ 0 };
|
||||
ClientInputId m_lastMigratedInputId = ClientInputId{ 0 }; // Used to resend inputs that were queued during a migration event
|
||||
HostFrameId m_serverMigrateFrameId = InvalidHostFrameId;
|
||||
|
||||
bool m_replayingInput = false; // True if we're replaying inputs under a correction event (use this to suppress effects or audio)
|
||||
bool m_allowMigrateClientInput = false; // True if this component was migrated, we will allow the client to send us migrated inputs (one time only)
|
||||
};
|
||||
}
|
||||
+6
-2
@@ -15,7 +15,8 @@
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzNetworking/Serialization/ISerializer.h>
|
||||
#include <AzNetworking/DataStructures/FixedSizeBitsetView.h>
|
||||
#include <Multiplayer/NetworkEntityHandle.h>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.h>
|
||||
#include <Multiplayer/MultiplayerStats.h>
|
||||
#include <Multiplayer/MultiplayerTypes.h>
|
||||
#include <Multiplayer/IMultiplayer.h>
|
||||
|
||||
@@ -62,7 +63,10 @@ namespace Multiplayer
|
||||
//! @}
|
||||
|
||||
NetEntityId GetNetEntityId() const;
|
||||
NetEntityRole GetNetEntityRole() const;
|
||||
bool IsAuthority() const;
|
||||
bool IsAutonomous() const;
|
||||
bool IsServer() const;
|
||||
bool IsClient() const;
|
||||
ConstNetworkEntityHandle GetEntityHandle() const;
|
||||
NetworkEntityHandle GetEntityHandle();
|
||||
void MarkDirty();
|
||||
+10
-2
@@ -14,7 +14,8 @@
|
||||
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <Multiplayer/MultiplayerComponent.h>
|
||||
#include <Multiplayer/Components/MultiplayerComponent.h>
|
||||
#include <Multiplayer/NetworkInput/IMultiplayerComponentInput.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -22,13 +23,15 @@ namespace Multiplayer
|
||||
{
|
||||
public:
|
||||
using PropertyNameLookupFunction = AZStd::function<const char*(PropertyIndex index)>;
|
||||
using RpcNameLookupFunction = AZStd::function<const char* (RpcIndex index)>;
|
||||
using RpcNameLookupFunction = AZStd::function<const char*(RpcIndex index)>;
|
||||
using AllocComponentInputFunction = AZStd::function<AZStd::unique_ptr<IMultiplayerComponentInput>()>;
|
||||
struct ComponentData
|
||||
{
|
||||
AZ::Name m_gemName;
|
||||
AZ::Name m_componentName;
|
||||
PropertyNameLookupFunction m_componentPropertyNameLookupFunction;
|
||||
RpcNameLookupFunction m_componentRpcNameLookupFunction;
|
||||
AllocComponentInputFunction m_allocComponentInputFunction;
|
||||
};
|
||||
|
||||
//! Registers a multiplayer component with the multiplayer system.
|
||||
@@ -36,6 +39,11 @@ namespace Multiplayer
|
||||
//! @return the NetComponentId assigned to this particular component
|
||||
NetComponentId RegisterMultiplayerComponent(const ComponentData& componentData);
|
||||
|
||||
//! Allocates a new component input for the provided netComponentId.
|
||||
//! @param netComponentId the NetComponentId to allocate a component input for
|
||||
//! @return pointer to the allocated component input, caller assumes ownership
|
||||
AZStd::unique_ptr<IMultiplayerComponentInput> AllocateComponentInput(NetComponentId netComponentId);
|
||||
|
||||
//! Returns the gem name associated with the provided NetComponentId.
|
||||
//! @param netComponentId the NetComponentId to return the gem name of
|
||||
//! @return the name of the gem that contains the requested component
|
||||
+8
-4
@@ -12,7 +12,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Multiplayer/NetworkEntityHandle.h>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
|
||||
namespace Multiplayer
|
||||
@@ -47,9 +47,13 @@ namespace Multiplayer
|
||||
//! @return the networkId for the entity that owns this controller
|
||||
NetEntityId GetNetEntityId() const;
|
||||
|
||||
//! Returns the networkRole for the entity that owns this controller.
|
||||
//! @return the networkRole for the entity that owns this controller
|
||||
NetEntityRole GetNetEntityRole() const;
|
||||
//! Returns true if this controller has authority.
|
||||
//! @return boolean true if this controller has authority
|
||||
bool IsAuthority() const;
|
||||
|
||||
//! Returns true if this controller has autonomy (can locally predict).
|
||||
//! @return boolean true if this controller has autonomy
|
||||
bool IsAutonomous() const;
|
||||
|
||||
//! Returns the raw AZ::Entity pointer for the entity that owns this controller.
|
||||
//! @return the raw AZ::Entity pointer for the entity that owns this controller
|
||||
+9
-4
@@ -20,10 +20,10 @@
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzNetworking/Serialization/ISerializer.h>
|
||||
#include <AzNetworking/ConnectionLayer/IConnection.h>
|
||||
#include <Multiplayer/ReplicationRecord.h>
|
||||
#include <Multiplayer/NetworkEntityHandle.h>
|
||||
#include <Multiplayer/IMultiplayerComponentInput.h>
|
||||
#include <Multiplayer/INetworkTime.h>
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.h>
|
||||
#include <Multiplayer/NetworkInput/IMultiplayerComponentInput.h>
|
||||
#include <Multiplayer/NetworkTime/INetworkTime.h>
|
||||
#include <Multiplayer/MultiplayerTypes.h>
|
||||
#include <AzCore/EBus/Event.h>
|
||||
|
||||
@@ -63,12 +63,16 @@ namespace Multiplayer
|
||||
|
||||
NetEntityRole GetNetEntityRole() const;
|
||||
bool IsAuthority() const;
|
||||
bool IsAutonomous() const;
|
||||
bool IsServer() const;
|
||||
bool IsClient() const;
|
||||
bool HasController() const;
|
||||
NetEntityId GetNetEntityId() const;
|
||||
const PrefabEntityId& GetPrefabEntityId() const;
|
||||
ConstNetworkEntityHandle GetEntityHandle() const;
|
||||
NetworkEntityHandle GetEntityHandle();
|
||||
|
||||
void SetAllowAutonomy(bool value);
|
||||
MultiplayerComponentInputVector AllocateComponentInputs();
|
||||
bool IsProcessingInput() const;
|
||||
void CreateInput(NetworkInput& networkInput, float deltaTime);
|
||||
@@ -155,6 +159,7 @@ namespace Multiplayer
|
||||
bool m_isProcessingInput = false;
|
||||
bool m_isMigrationDataValid = false;
|
||||
bool m_needsToBeStopped = false;
|
||||
bool m_allowAutonomy = false; // Set to true for the hosts controlled entity
|
||||
|
||||
friend class NetworkEntityManager;
|
||||
friend class EntityReplicationManager;
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 <Source/AutoGen/NetworkTransformComponent.AutoComponent.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
class NetworkTransformComponent
|
||||
: public NetworkTransformComponentBase
|
||||
{
|
||||
public:
|
||||
AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkTransformComponent, s_networkTransformComponentConcreteUuid, Multiplayer::NetworkTransformComponentBase);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
NetworkTransformComponent();
|
||||
|
||||
void OnInit() override;
|
||||
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
|
||||
private:
|
||||
void OnRotationChangedEvent(const AZ::Quaternion& rotation);
|
||||
void OnTranslationChangedEvent(const AZ::Vector3& translation);
|
||||
void OnScaleChangedEvent(const AZ::Vector3& scale);
|
||||
|
||||
AZ::Event<AZ::Quaternion>::Handler m_rotationEventHandler;
|
||||
AZ::Event<AZ::Vector3>::Handler m_translationEventHandler;
|
||||
AZ::Event<AZ::Vector3>::Handler m_scaleEventHandler;
|
||||
};
|
||||
|
||||
class NetworkTransformComponentController
|
||||
: public NetworkTransformComponentControllerBase
|
||||
{
|
||||
public:
|
||||
NetworkTransformComponentController(NetworkTransformComponent& parent);
|
||||
|
||||
void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
|
||||
|
||||
private:
|
||||
void OnTransformChangedEvent(const AZ::Transform& worldTm);
|
||||
|
||||
AZ::TransformChangedEvent::Handler m_transformChangedHandler;
|
||||
};
|
||||
}
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Multiplayer/INetworkEntityManager.h>
|
||||
#include <Multiplayer/NetworkEntity/INetworkEntityManager.h>
|
||||
#include <AzNetworking/ConnectionLayer/IConnection.h>
|
||||
|
||||
namespace Multiplayer
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Multiplayer/INetworkEntityManager.h>
|
||||
#include <Multiplayer/NetworkEntity/INetworkEntityManager.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
@@ -15,8 +15,9 @@
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzNetworking/ConnectionLayer/IConnection.h>
|
||||
#include <AzNetworking/DataStructures/ByteBuffer.h>
|
||||
#include <Multiplayer/INetworkEntityManager.h>
|
||||
#include <Multiplayer/INetworkTime.h>
|
||||
#include <Multiplayer/Components/MultiplayerComponentRegistry.h>
|
||||
#include <Multiplayer/NetworkEntity/INetworkEntityManager.h>
|
||||
#include <Multiplayer/NetworkTime/INetworkTime.h>
|
||||
#include <Multiplayer/MultiplayerStats.h>
|
||||
|
||||
namespace AzNetworking
|
||||
@@ -101,28 +102,6 @@ namespace Multiplayer
|
||||
//! @return pointer to the network entity manager instance bound to this multiplayer instance
|
||||
virtual INetworkEntityManager* GetNetworkEntityManager() = 0;
|
||||
|
||||
//! Returns the gem name associated with the provided component index.
|
||||
//! @param netComponentId the componentId to return the gem name of
|
||||
//! @return the name of the gem that contains the requested component
|
||||
virtual const char* GetComponentGemName(NetComponentId netComponentId) const = 0;
|
||||
|
||||
//! Returns the component name associated with the provided component index.
|
||||
//! @param netComponentId the componentId to return the component name of
|
||||
//! @return the name of the component
|
||||
virtual const char* GetComponentName(NetComponentId netComponentId) const = 0;
|
||||
|
||||
//! Returns the property name associated with the provided component index and property index.
|
||||
//! @param netComponentId the component index to return the property name of
|
||||
//! @param propertyIndex the index of the network property to return the property name of
|
||||
//! @return the name of the network property
|
||||
virtual const char* GetComponentPropertyName(NetComponentId netComponentId, PropertyIndex propertyIndex) const = 0;
|
||||
|
||||
//! Returns the Rpc name associated with the provided component index and rpc index.
|
||||
//! @param netComponentId the componentId to return the property name of
|
||||
//! @param rpcIndex the index of the rpc to return the rpc name of
|
||||
//! @return the name of the requested rpc
|
||||
virtual const char* GetComponentRpcName(NetComponentId netComponentId, RpcIndex rpcIndex) const = 0;
|
||||
|
||||
//! Retrieve the stats object bound to this multiplayer instance.
|
||||
//! @return the stats object bound to this multiplayer instance
|
||||
MultiplayerStats& GetStats() { return m_stats; }
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,193 +0,0 @@
|
||||
/*
|
||||
* 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 <Multiplayer/MultiplayerStats.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
MultiplayerStats::Metric::Metric()
|
||||
{
|
||||
AZStd::uninitialized_fill_n(m_callHistory.data(), RingbufferSamples, 0);
|
||||
AZStd::uninitialized_fill_n(m_byteHistory.data(), RingbufferSamples, 0);
|
||||
}
|
||||
|
||||
void MultiplayerStats::ReserveComponentStats(NetComponentId netComponentId, uint16_t propertyCount, uint16_t rpcCount)
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
if (m_componentStats.size() <= netComponentIndex)
|
||||
{
|
||||
m_componentStats.resize(netComponentIndex + 1);
|
||||
}
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent.resize(propertyCount);
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv.resize(propertyCount);
|
||||
m_componentStats[netComponentIndex].m_rpcsSent.resize(rpcCount);
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv.resize(rpcCount);
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes)
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
const uint16_t propertyIndex = aznumeric_cast<uint16_t>(propertyId);
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_totalCalls++;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes)
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
const uint16_t propertyIndex = aznumeric_cast<uint16_t>(propertyId);
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_totalCalls++;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t 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++;
|
||||
m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordRpcReceived(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes)
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
const uint16_t rpcIndex = aznumeric_cast<uint16_t>(rpcId);
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_totalCalls++;
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::TickStats(AZ::TimeMs metricFrameTimeMs)
|
||||
{
|
||||
m_totalHistoryTimeMs = metricFrameTimeMs * static_cast<AZ::TimeMs>(RingbufferSamples);
|
||||
m_recordMetricIndex = ++m_recordMetricIndex % RingbufferSamples;
|
||||
for (ComponentStats& componentStats : m_componentStats)
|
||||
{
|
||||
for (Metric& metric : componentStats.m_propertyUpdatesSent)
|
||||
{
|
||||
metric.m_callHistory[m_recordMetricIndex] = 0;
|
||||
metric.m_byteHistory[m_recordMetricIndex] = 0;
|
||||
}
|
||||
for (Metric& metric : componentStats.m_propertyUpdatesRecv)
|
||||
{
|
||||
metric.m_callHistory[m_recordMetricIndex] = 0;
|
||||
metric.m_byteHistory[m_recordMetricIndex] = 0;
|
||||
}
|
||||
for (Metric& metric : componentStats.m_rpcsSent)
|
||||
{
|
||||
metric.m_callHistory[m_recordMetricIndex] = 0;
|
||||
metric.m_byteHistory[m_recordMetricIndex] = 0;
|
||||
}
|
||||
for (Metric& metric : componentStats.m_rpcsRecv)
|
||||
{
|
||||
metric.m_callHistory[m_recordMetricIndex] = 0;
|
||||
metric.m_byteHistory[m_recordMetricIndex] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(NetComponentId netComponentId) const
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
return SumMetricVector(m_componentStats[netComponentIndex].m_propertyUpdatesSent);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentPropertyUpdateRecvMetrics(NetComponentId netComponentId) const
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
return SumMetricVector(m_componentStats[netComponentIndex].m_propertyUpdatesRecv);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsSentMetrics(NetComponentId netComponentId) const
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
return SumMetricVector(m_componentStats[netComponentIndex].m_rpcsSent);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsRecvMetrics(NetComponentId netComponentId) const
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
return SumMetricVector(m_componentStats[netComponentIndex].m_rpcsRecv);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalPropertyUpdateSentMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
const NetComponentId netComponentId = aznumeric_cast<NetComponentId>(index);
|
||||
CombineMetrics(result, CalculateComponentPropertyUpdateSentMetrics(netComponentId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalPropertyUpdateRecvMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
const NetComponentId netComponentId = aznumeric_cast<NetComponentId>(index);
|
||||
CombineMetrics(result, CalculateComponentPropertyUpdateRecvMetrics(netComponentId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalRpcsSentMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
const NetComponentId netComponentId = aznumeric_cast<NetComponentId>(index);
|
||||
CombineMetrics(result, CalculateComponentRpcsSentMetrics(netComponentId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalRpcsRecvMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
const NetComponentId netComponentId = aznumeric_cast<NetComponentId>(index);
|
||||
CombineMetrics(result, CalculateComponentRpcsRecvMetrics(netComponentId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Multiplayer/MultiplayerTypes.h>
|
||||
#include <Multiplayer/NetworkEntityHandle.h>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/EBus/Event.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
+1
-1
@@ -138,4 +138,4 @@ namespace Multiplayer
|
||||
};
|
||||
}
|
||||
|
||||
#include <Multiplayer/NetworkEntityHandle.inl>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.inl>
|
||||
+1
-1
@@ -28,7 +28,7 @@ namespace Multiplayer
|
||||
{
|
||||
public:
|
||||
virtual ~IMultiplayerComponentInput() = default;
|
||||
virtual NetComponentId GetComponentId() const = 0;
|
||||
virtual NetComponentId GetNetComponentId() const = 0;
|
||||
virtual bool Serialize(AzNetworking::ISerializer& serializer) = 0;
|
||||
};
|
||||
|
||||
+7
-7
@@ -12,9 +12,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Multiplayer/IMultiplayerComponentInput.h>
|
||||
#include <Multiplayer/INetworkTime.h>
|
||||
#include <Multiplayer/NetworkEntityHandle.h>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.h>
|
||||
#include <Multiplayer/NetworkInput/IMultiplayerComponentInput.h>
|
||||
#include <Multiplayer/NetworkTime/INetworkTime.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
|
||||
namespace Multiplayer
|
||||
@@ -57,15 +57,15 @@ namespace Multiplayer
|
||||
IMultiplayerComponentInput* FindComponentInput(NetComponentId componentId);
|
||||
|
||||
template <class InputType>
|
||||
const InputType* FindInput() const
|
||||
const InputType* FindComponentInput() const
|
||||
{
|
||||
return static_cast<const InputType*>(FindInput(InputType::s_Type));
|
||||
return static_cast<const InputType*>(FindComponentInput(InputType::s_netComponentId));
|
||||
}
|
||||
|
||||
template <typename InputType>
|
||||
InputType* FindInput()
|
||||
InputType* FindComponentInput()
|
||||
{
|
||||
return static_cast<InputType*>(FindInput(InputType::s_Type));
|
||||
return static_cast<InputType*>(FindComponentInput(InputType::s_netComponentId));
|
||||
}
|
||||
|
||||
private:
|
||||
+2
-2
@@ -12,7 +12,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Multiplayer/INetworkTime.h>
|
||||
#include <Multiplayer/NetworkTime/INetworkTime.h>
|
||||
#include <AzNetworking/Serialization/ISerializer.h>
|
||||
#include <AzNetworking/ConnectionLayer/IConnection.h>
|
||||
#include <AzNetworking/Utilities/NetworkCommon.h>
|
||||
@@ -115,4 +115,4 @@ namespace AZ
|
||||
AZ_TYPE_INFO_TEMPLATE(Multiplayer::RewindableObject, "{B2937B44-FEE1-4277-B1E0-863DE76D363F}", AZ_TYPE_INFO_TYPENAME, AZ_TYPE_INFO_AUTO);
|
||||
}
|
||||
|
||||
#include <Multiplayer/RewindableObject.inl>
|
||||
#include <Multiplayer/NetworkTime/RewindableObject.inl>
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Multiplayer/MultiplayerTypes.h>
|
||||
#include <Multiplayer/NetworkEntityHandle.h>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
|
||||
namespace Multiplayer
|
||||
Reference in New Issue
Block a user