Integrating github/staging through commit ab87ed9

This commit is contained in:
alexpete
2021-04-09 11:27:37 -07:00
parent ae62a97894
commit 1044dc3da1
1582 changed files with 29374 additions and 519051 deletions
@@ -18,9 +18,9 @@
#include <Source/NetworkEntity/NetworkEntityTracker.h>
#include <Source/NetworkEntity/NetworkEntityRpcMessage.h>
#include <Source/Components/NetBindComponent.h>
#include <Source/Components/NetworkTransformComponent.h>
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
//#include "Generated/NovaGameCommon/Component/Multiplayer/LocationComponentCommon.AutoComponent.h"
#include <Include/IMultiplayer.h>
#include <AzNetworking/PacketLayer/IPacket.h>
#include <AzNetworking/Serialization/ISerializer.h>
@@ -447,7 +447,11 @@ namespace Multiplayer
void EntityReplicator::DeferRpcMessage(NetworkEntityRpcMessage& entityRpcMessage)
{
//Multiplayer::GetPacketHandlerMetricsInstance().LogSentRpc(entityRpcMessage.GetEntityComponentType(), entityRpcMessage.GetRpcMessageType(), entityRpcMessage.GetEstimatedSerializeSize());
// 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();
m_replicationManager.AddDeferredRpcMessage(entityRpcMessage);
}
@@ -627,8 +631,10 @@ namespace Multiplayer
bool EntityReplicator::HandleRpcMessage(NetworkEntityRpcMessage& entityRpcMessage)
{
// Received rpc metrics
//ScopedTimer processTimer(Multiplayer::GetPacketHandlerMetricsInstance().LogReceivedRpc(entityRpcMessage.GetEntityComponentType(), entityRpcMessage.GetRpcMessageType(), entityRpcMessage.GetEstimatedSerializeSize()));
// 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();
if (!m_netBindComponent)
{
@@ -16,12 +16,14 @@ namespace Multiplayer
{
ReplicationRecordStats::ReplicationRecordStats
(
uint32_t authorityToAuthorityCount,
uint32_t authorityToClientCount,
uint32_t authorityToServerCount,
uint32_t authorityToAutonomousCount,
uint32_t autonomousToAuthorityCount
)
: m_authorityToClientCount(authorityToClientCount)
: m_authorityToAuthorityCount(authorityToAuthorityCount)
, m_authorityToClientCount(authorityToClientCount)
, m_authorityToServerCount(authorityToServerCount)
, m_authorityToAutonomousCount(authorityToAutonomousCount)
, m_autonomousToAuthorityCount(autonomousToAuthorityCount)
@@ -31,7 +33,8 @@ namespace Multiplayer
bool ReplicationRecordStats::operator ==(const ReplicationRecordStats& rhs) const
{
return (m_authorityToClientCount == rhs.m_authorityToClientCount)
return (m_authorityToAuthorityCount == rhs.m_authorityToAuthorityCount)
&& (m_authorityToClientCount == rhs.m_authorityToClientCount)
&& (m_authorityToServerCount == rhs.m_authorityToServerCount)
&& (m_authorityToAutonomousCount == rhs.m_authorityToAutonomousCount)
&& (m_autonomousToAuthorityCount == rhs.m_autonomousToAuthorityCount);
@@ -41,6 +44,7 @@ namespace Multiplayer
{
return ReplicationRecordStats
{
(m_authorityToAuthorityCount - rhs.m_authorityToAuthorityCount),
(m_authorityToClientCount - rhs.m_authorityToClientCount),
(m_authorityToServerCount - rhs.m_authorityToServerCount),
(m_authorityToAutonomousCount - rhs.m_authorityToAutonomousCount),
@@ -67,6 +71,7 @@ namespace Multiplayer
bool ReplicationRecord::AreAllBitsConsumed() const
{
bool ret = true;
ret &= m_authorityToAuthorityConsumedBits == m_authorityToAuthority.GetSize();
ret &= m_authorityToClientConsumedBits == m_authorityToClient.GetSize();
ret &= m_authorityToServerConsumedBits == m_authorityToServer.GetSize();
ret &= m_authorityToAutonomousConsumedBits == m_authorityToAutonomous.GetSize();
@@ -76,6 +81,7 @@ namespace Multiplayer
void ReplicationRecord::ResetConsumedBits()
{
m_authorityToAuthorityConsumedBits = 0;
m_authorityToClientConsumedBits = 0;
m_authorityToServerConsumedBits = 0;
m_authorityToAutonomousConsumedBits = 0;
@@ -86,7 +92,11 @@ namespace Multiplayer
{
ResetConsumedBits();
uint32_t recordSize = m_authorityToClient.GetSize();
uint32_t recordSize = m_authorityToAuthority.GetSize();
m_authorityToAuthority.Clear();
m_authorityToAuthority.Resize(recordSize);
recordSize = m_authorityToClient.GetSize();
m_authorityToClient.Clear();
m_authorityToClient.Resize(recordSize);
@@ -105,6 +115,7 @@ namespace Multiplayer
void ReplicationRecord::Append(const ReplicationRecord &rhs)
{
m_authorityToAuthority |= rhs.m_authorityToAuthority;
m_authorityToClient |= rhs.m_authorityToClient;
m_authorityToServer |= rhs.m_authorityToServer;
m_authorityToAutonomous |= rhs.m_authorityToAutonomous;
@@ -113,6 +124,7 @@ namespace Multiplayer
void ReplicationRecord::Subtract(const ReplicationRecord &rhs)
{
m_authorityToAuthority.Subtract(rhs.m_authorityToAuthority);
m_authorityToClient.Subtract(rhs.m_authorityToClient);
m_authorityToServer.Subtract(rhs.m_authorityToServer);
m_authorityToAutonomous.Subtract(rhs.m_authorityToAutonomous);
@@ -122,6 +134,10 @@ namespace Multiplayer
bool ReplicationRecord::HasChanges() const
{
bool hasChanges(false);
if (ContainsAuthorityToAuthorityBits())
{
hasChanges = hasChanges ? hasChanges : m_authorityToAuthority.AnySet();
}
if (ContainsAuthorityToClientBits())
{
hasChanges = hasChanges ? hasChanges : m_authorityToClient.AnySet();
@@ -143,25 +159,37 @@ namespace Multiplayer
bool ReplicationRecord::Serialize(AzNetworking::ISerializer& serializer)
{
if (ContainsAuthorityToAuthorityBits())
{
serializer.Serialize(m_authorityToAuthority, "AuthorityToAuthorityRecord");
}
if (ContainsAuthorityToClientBits())
{
serializer.Serialize(m_authorityToClient, "ServerToClientsRecord");
serializer.Serialize(m_authorityToClient, "AuthorityToClientRecord");
}
if (ContainsAuthorityToServerBits())
{
serializer.Serialize(m_authorityToServer, "ServerToServersRecord");
serializer.Serialize(m_authorityToServer, "AuthorityToServerRecord");
}
if (ContainsAuthorityToAutonomousBits())
{
serializer.Serialize(m_authorityToAutonomous, "ServerToAutonomousRecord");
serializer.Serialize(m_authorityToAutonomous, "AuthorityToAutonomousRecord");
}
if (ContainsAutonomousToAuthorityBits())
{
serializer.Serialize(m_autonomousToAuthority, "ClientToServersRecord");
serializer.Serialize(m_autonomousToAuthority, "AutonomousToAuthorityRecord");
}
return serializer.IsValid();
}
void ReplicationRecord::ConsumeAuthorityToAuthorityBits(uint32_t consumedBits)
{
if (ContainsAuthorityToAuthorityBits())
{
m_authorityToAuthorityConsumedBits += consumedBits;
}
}
void ReplicationRecord::ConsumeAuthorityToClientBits(uint32_t consumedBits)
{
if (ContainsAuthorityToClientBits())
@@ -194,6 +222,12 @@ namespace Multiplayer
}
}
bool ReplicationRecord::ContainsAuthorityToAuthorityBits() const
{
return (m_netEntityRole == NetEntityRole::Authority)
|| (m_netEntityRole == NetEntityRole::InvalidRole);
}
bool ReplicationRecord::ContainsAuthorityToClientBits() const
{
return (m_netEntityRole != NetEntityRole::Authority)
@@ -218,6 +252,11 @@ namespace Multiplayer
|| (m_netEntityRole == NetEntityRole::InvalidRole);
}
uint32_t ReplicationRecord::GetRemainingAuthorityToAuthorityBits() const
{
return m_authorityToAuthorityConsumedBits < m_authorityToAuthority.GetValidBitCount() ? m_authorityToAuthority.GetValidBitCount() - m_authorityToAuthorityConsumedBits : 0;
}
uint32_t ReplicationRecord::GetRemainingAuthorityToClientBits() const
{
return m_authorityToClientConsumedBits < m_authorityToClient.GetValidBitCount() ? m_authorityToClient.GetValidBitCount() - m_authorityToClientConsumedBits : 0;
@@ -242,6 +281,7 @@ namespace Multiplayer
{
return ReplicationRecordStats
{
m_authorityToAuthorityConsumedBits,
m_authorityToClientConsumedBits,
m_authorityToServerConsumedBits,
m_authorityToAutonomousConsumedBits,
@@ -24,12 +24,14 @@ namespace Multiplayer
ReplicationRecordStats() = default;
ReplicationRecordStats
(
uint32_t authorityToAuthorityCount,
uint32_t authorityToClientCount,
uint32_t authorityToServerCount,
uint32_t authorityToAutonomousCount,
uint32_t autonomousToAuthorityCount
);
uint32_t m_authorityToAuthorityCount = 0;
uint32_t m_authorityToClientCount = 0;
uint32_t m_authorityToServerCount = 0;
uint32_t m_authorityToAutonomousCount = 0;
@@ -61,16 +63,19 @@ namespace Multiplayer
bool Serialize(AzNetworking::ISerializer& serializer);
void ConsumeAuthorityToAuthorityBits(uint32_t consumedBits);
void ConsumeAuthorityToClientBits(uint32_t consumedBits);
void ConsumeAuthorityToServerBits(uint32_t consumedBits);
void ConsumeAuthorityToAutonomousBits(uint32_t consumedBits);
void ConsumeAutonomousToAuthorityBits(uint32_t consumedBits);
bool ContainsAuthorityToAuthorityBits() const;
bool ContainsAuthorityToClientBits() const;
bool ContainsAuthorityToServerBits() const;
bool ContainsAuthorityToAutonomousBits() const;
bool ContainsAutonomousToAuthorityBits() const;
uint32_t GetRemainingAuthorityToAuthorityBits() const;
uint32_t GetRemainingAuthorityToClientBits() const;
uint32_t GetRemainingAuthorityToServerBits() const;
uint32_t GetRemainingAuthorityToAutonomousBits() const;
@@ -79,11 +84,13 @@ namespace Multiplayer
ReplicationRecordStats GetStats() const;
using RecordBitset = AzNetworking::FixedSizeVectorBitset<MaxRecordBits>;
RecordBitset m_authorityToAuthority;
RecordBitset m_authorityToClient;
RecordBitset m_authorityToServer;
RecordBitset m_authorityToAutonomous;
RecordBitset m_autonomousToAuthority;
uint32_t m_authorityToAuthorityConsumedBits = 0;
uint32_t m_authorityToClientConsumedBits = 0;
uint32_t m_authorityToServerConsumedBits = 0;
uint32_t m_authorityToAutonomousConsumedBits = 0;
@@ -24,10 +24,14 @@
namespace Multiplayer
{
AZ_CVAR(bool, net_DebugCheckNetworkEntityManager, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Enables extra debug checks inside the NetworkEntityManager");
AZ_CVAR(AZ::TimeMs, net_EntityDomainUpdateMs, AZ::TimeMs{ 500 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Frequency for updating the entity domain in ms");
NetworkEntityManager::NetworkEntityManager()
: m_networkEntityAuthorityTracker(*this)
, m_removeEntitiesEvent([this] { RemoveEntities(); }, AZ::Name("NetworkEntityManager remove entities event"))
, m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event"))
, m_entityAddedEventHandler([this](AZ::Entity* entity) { OnEntityAdded(entity); })
, m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); })
{
AZ::Interface<INetworkEntityManager>::Register(this);
}
@@ -37,6 +41,20 @@ namespace Multiplayer
AZ::Interface<INetworkEntityManager>::Unregister(this);
}
void NetworkEntityManager::Initialize(HostId hostId, AZStd::unique_ptr<IEntityDomain> entityDomain)
{
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
{
// Null guard needed for unit tests
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler);
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler);
}
m_hostId = hostId;
m_entityDomain = AZStd::move(entityDomain);
m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true);
}
NetworkEntityTracker* NetworkEntityManager::GetNetworkEntityTracker()
{
return &m_networkEntityTracker;
@@ -74,10 +92,9 @@ namespace Multiplayer
{
if (net_DebugCheckNetworkEntityManager)
{
NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
AZ_Assert(netBindComponent, "No NetBindComponent found on networked entity");
const bool isClientOnlyEntity = false;// (ServerIdFromEntityId(it->first) == InvalidHostId);
AZ_Assert(netBindComponent->IsAuthority() || isClientOnlyEntity, "Trying to delete a proxy entity, this will lead to issues deserializing entity updates");
AZ_Assert(entityHandle.GetNetBindComponent(), "No NetBindComponent found on networked entity");
[[maybe_unused]] const bool isClientOnlyEntity = false;// (ServerIdFromEntityId(it->first) == InvalidHostId);
AZ_Assert(entityHandle.GetNetBindComponent()->IsAuthority() || isClientOnlyEntity, "Trying to delete a proxy entity, this will lead to issues deserializing entity updates");
}
m_removeList.push_back(entityHandle.GetNetEntityId());
m_removeEntitiesEvent.Enqueue(AZ::TimeMs{ 0 });
@@ -185,6 +202,100 @@ namespace Multiplayer
m_localDeferredRpcMessages.emplace_back(AZStd::move(message));
}
void NetworkEntityManager::DispatchLocalDeferredRpcMessages()
{
for (NetworkEntityRpcMessage& rpcMessage : m_localDeferredRpcMessages)
{
AZ::Entity* entity = m_networkEntityTracker.GetRaw(rpcMessage.GetEntityId());
if (entity != nullptr)
{
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
AZ_Assert(netBindComponent != nullptr, "Attempting to send an RPC to an entity with no NetBindComponent");
netBindComponent->HandleRpcMessage(NetEntityRole::Server, rpcMessage);
}
}
m_localDeferredRpcMessages.clear();
}
void NetworkEntityManager::UpdateEntityDomain()
{
if (m_entityDomain == nullptr)
{
return;
}
m_entitiesNotInDomain.clear();
m_entityDomain->RetrieveEntitiesNotInDomain(m_entitiesNotInDomain);
for (NetEntityId exitingId : m_entitiesNotInDomain)
{
OnEntityExitDomain(exitingId);
}
}
void NetworkEntityManager::OnEntityExitDomain(NetEntityId entityId)
{
bool safeToExit = true;
NetworkEntityHandle entityHandle = m_networkEntityTracker.Get(entityId);
// ClientAutonomous entities need special handling here. When we migrate a player's entity the player's client must tell the new server which
// entity they were controlling. If we tell them to migrate before they know which entity they control it results in them requesting a new entity
// from the new server, resulting in an orphaned PlayerChar. PlayerControllerComponentServerAuthority::PlayerClientHasControlledEntity()
// will tell us whether the client sent an RPC acknowledging that they now know which entity is theirs.
if (AZ::Entity* entity = entityHandle.GetEntity())
{
//if (PlayerComponent::Authority* playerController = FindController<PlayerComponent::Authority>(nonConstExitingEntityPtr))
//{
// safeToExit = playerController->PlayerClientHasControlledEntity();
//}
}
// We also need special handling for the EntityHierarchyComponent as well, since related entities need to be migrated together
//auto* hierarchyController = FindController<EntityHierarchyComponent::Authority>(nonConstExitingEntityPtr);
//if (hierarchyController)
//{
// if (hierarchyController->GetParentRelatedEntity())
// {
// safeToExit = false;
// }
//}
// Validate that we aren't already planning to remove this entity
if (safeToExit)
{
for (auto entityId : m_removeList)
{
if (entityId == entityId)
{
safeToExit = false;
}
}
}
if (safeToExit)
{
m_entityExitDomainEvent.Signal(entityHandle);
}
}
void NetworkEntityManager::OnEntityAdded(AZ::Entity* entity)
{
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
if (netBindComponent != nullptr)
{
const NetEntityId netEntityId = m_nextEntityId++;
netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority);
}
}
void NetworkEntityManager::OnEntityRemoved(AZ::Entity* entity)
{
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
if (netBindComponent != nullptr)
{
MarkForRemoval(netBindComponent->GetEntityHandle());
}
}
void NetworkEntityManager::RemoveEntities()
{
//RewindableObjectState::ClearRewoundEntities();
@@ -213,10 +324,10 @@ namespace Multiplayer
// Delete Entity, method depends on how it was loaded
// Try slice removal first, then force delete
AZ::Entity* rawEntity = removeEntity.GetEntity();
//AZ::Entity* rawEntity = removeEntity.GetEntity();
//if (!rootSlice->RemoveEntity(rawEntity))
//{
delete rawEntity;
// delete rawEntity;
//}
}
@@ -13,10 +13,12 @@
#pragma once
#include <AzCore/EBus/ScheduledEvent.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <Source/NetworkEntity/INetworkEntityManager.h>
#include <Source/NetworkEntity/NetworkEntityAuthorityTracker.h>
#include <Source/NetworkEntity/NetworkEntityTracker.h>
#include <Source/NetworkEntity/NetworkEntityRpcMessage.h>
#include <Source/EntityDomains/IEntityDomain.h>
namespace Multiplayer
{
@@ -29,6 +31,9 @@ namespace Multiplayer
NetworkEntityManager();
~NetworkEntityManager();
//! Only invoked for authoritative hosts
void Initialize(HostId hostId, AZStd::unique_ptr<IEntityDomain> entityDomain);
//! INetworkEntityManager overrides.
//! @{
NetworkEntityTracker* GetNetworkEntityTracker() override;
@@ -53,8 +58,14 @@ namespace Multiplayer
void HandleLocalRpcMessage(NetworkEntityRpcMessage& message) override;
//! @}
void DispatchLocalDeferredRpcMessages();
void UpdateEntityDomain();
void OnEntityExitDomain(NetEntityId entityId);
private:
void OnEntityAdded(AZ::Entity* entity);
void OnEntityRemoved(AZ::Entity* entity);
void RemoveEntities();
NetworkEntityTracker m_networkEntityTracker;
@@ -63,14 +74,22 @@ namespace Multiplayer
AZStd::vector<NetEntityId> m_removeList;
AZStd::vector<AZ::Entity*> m_nonNetworkedEntities; // Contains entities that we've instantiated, but are not networked entities
AZStd::unique_ptr<IEntityDomain> m_entityDomain;
AZ::ScheduledEvent m_updateEntityDomainEvent;
IEntityDomain::EntitiesNotInDomain m_entitiesNotInDomain;
OwnedEntitySet m_ownedEntities;
EntityExitDomainEvent m_entityExitDomainEvent;
AZ::Event<> m_onEntityMarkedDirty;
AZ::Event<> m_onEntityNotifyChanges;
ControllersActivatedEvent m_controllersActivatedEvent;
ControllersDeactivatedEvent m_controllersDeactivatedEvent;
AZ::EntityAddedEvent::Handler m_entityAddedEventHandler;
AZ::EntityRemovedEvent::Handler m_entityRemovedEventHandler;
HostId m_hostId = InvalidHostId;
int32_t m_nextEntityIndex = 0;
NetEntityId m_nextEntityId = NetEntityId{ 0 };
// Local RPCs are buffered and dispatched at the end of the frame rather than processed immediately
// This is done to prevent local and network sent RPC's from having different dispatch behaviours