NetBindComponent::SetOwningConnectionId is for a hierarchy based on its root's network entity

- for hierarchies, on both servers and clients NetBindComponent::SetOwningConnectionId is set for the all involved entities based on the root entity owning connection id
- added new unit tests to cover these scenarios
- all unit tests pass, hierarchy benchmarks remain unaffected
This commit is contained in:
Olex Lozitskiy
2021-10-22 11:09:30 -04:00
committed by GitHub
6 changed files with 247 additions and 62 deletions
@@ -129,34 +129,48 @@ namespace Multiplayer
handler.Connect(m_networkHierarchyLeaveEvent);
}
void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot)
void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* previousHierarchyRoot, AZ::Entity* newHierarchyRoot)
{
if (m_rootEntity != hierarchyRoot)
if (newHierarchyRoot)
{
m_rootEntity = hierarchyRoot;
if (m_rootEntity != newHierarchyRoot)
{
m_rootEntity = newHierarchyRoot;
if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority)
{
NetworkHierarchyChildComponentController* controller = static_cast<NetworkHierarchyChildComponentController*>(GetController());
const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(m_rootEntity->GetId());
controller->SetHierarchyRoot(netRootId);
}
GetNetBindComponent()->SetOwningConnectionId(m_rootEntity->FindComponent<NetBindComponent>()->GetOwningConnectionId());
m_networkHierarchyChangedEvent.Signal(m_rootEntity->GetId());
}
}
else if ((previousHierarchyRoot && m_rootEntity == previousHierarchyRoot) || !previousHierarchyRoot)
{
m_rootEntity = nullptr;
if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority)
{
NetworkHierarchyChildComponentController* controller = static_cast<NetworkHierarchyChildComponentController*>(GetController());
if (m_rootEntity)
{
const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(m_rootEntity->GetId());
controller->SetHierarchyRoot(netRootId);
m_networkHierarchyChangedEvent.Signal(m_rootEntity->GetId());
}
else
{
controller->SetHierarchyRoot(InvalidNetEntityId);
m_networkHierarchyLeaveEvent.Signal();
}
controller->SetHierarchyRoot(InvalidNetEntityId);
}
if (m_rootEntity == nullptr)
{
NotifyChildrenHierarchyDisbanded();
}
GetNetBindComponent()->SetOwningConnectionId(m_previousOwningConnectionId);
m_networkHierarchyLeaveEvent.Signal();
NotifyChildrenHierarchyDisbanded();
}
}
void NetworkHierarchyChildComponent::SetOwningConnectionId(AzNetworking::ConnectionId connectionId)
{
NetworkHierarchyChildComponentBase::SetOwningConnectionId(connectionId);
if (IsHierarchicalChild() == false)
{
m_previousOwningConnectionId = connectionId;
}
}
@@ -180,14 +194,18 @@ namespace Multiplayer
if (m_rootEntity != newRoot)
{
m_rootEntity = newRoot;
m_previousOwningConnectionId = GetNetBindComponent()->GetOwningConnectionId();
GetNetBindComponent()->SetOwningConnectionId(m_rootEntity->FindComponent<NetBindComponent>()->GetOwningConnectionId());
m_networkHierarchyChangedEvent.Signal(m_rootEntity->GetId());
}
}
else
{
GetNetBindComponent()->SetOwningConnectionId(m_previousOwningConnectionId);
m_isHierarchyEnabled = false;
m_rootEntity = nullptr;
m_networkHierarchyLeaveEvent.Signal();
}
}
@@ -203,11 +221,11 @@ namespace Multiplayer
{
if (auto* hierarchyChildComponent = childEntity->FindComponent<NetworkHierarchyChildComponent>())
{
hierarchyChildComponent->SetTopLevelHierarchyRootEntity(nullptr);
hierarchyChildComponent->SetTopLevelHierarchyRootEntity(nullptr, nullptr);
}
else if (auto* hierarchyRootComponent = childEntity->FindComponent<NetworkHierarchyRootComponent>())
{
hierarchyRootComponent->SetTopLevelHierarchyRootEntity(nullptr);
hierarchyRootComponent->SetTopLevelHierarchyRootEntity(nullptr, nullptr);
}
}
}
@@ -107,7 +107,7 @@ namespace Multiplayer
{
if (const AZ::Entity* childEntity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(childEntityId))
{
SetRootForEntity(nullptr, childEntity);
SetRootForEntity(GetEntity(), nullptr, childEntity);
}
}
}
@@ -209,7 +209,7 @@ namespace Multiplayer
auto [rootComponent, childComponent] = GetHierarchyComponents(parentEntity);
if (rootComponent == nullptr && childComponent == nullptr)
{
RebuildHierarchy();
SetRootForEntity(nullptr, nullptr, GetEntity());
}
else
{
@@ -219,7 +219,7 @@ namespace Multiplayer
else
{
// Detached from parent
RebuildHierarchy();
SetRootForEntity(nullptr, nullptr, GetEntity());
}
}
@@ -247,14 +247,14 @@ namespace Multiplayer
{
// This is a newly added entity to the network hierarchy.
hierarchyChanged = true;
SetRootForEntity(GetEntity(), currentEntity);
SetRootForEntity(nullptr, GetEntity(), currentEntity);
}
}
// These entities were removed since last rebuild.
for (const AZ::Entity* previousEntity : previousEntities)
{
SetRootForEntity(nullptr, previousEntity);
SetRootForEntity(GetEntity(), nullptr, previousEntity);
}
if (!previousEntities.empty())
@@ -307,45 +307,66 @@ namespace Multiplayer
}
}
void NetworkHierarchyRootComponent::SetRootForEntity(AZ::Entity* root, const AZ::Entity* childEntity)
void NetworkHierarchyRootComponent::SetRootForEntity(AZ::Entity* previousKnownRoot, AZ::Entity* newRoot, const AZ::Entity* childEntity)
{
auto [hierarchyRootComponent, hierarchyChildComponent] = GetHierarchyComponents(childEntity);
if (hierarchyChildComponent)
{
hierarchyChildComponent->SetTopLevelHierarchyRootEntity(root);
hierarchyChildComponent->SetTopLevelHierarchyRootEntity(previousKnownRoot, newRoot);
}
else if (hierarchyRootComponent)
{
hierarchyRootComponent->SetTopLevelHierarchyRootEntity(root);
hierarchyRootComponent->SetTopLevelHierarchyRootEntity(previousKnownRoot, newRoot);
}
}
void NetworkHierarchyRootComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot)
void NetworkHierarchyRootComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* previousHierarchyRoot, AZ::Entity* newHierarchyRoot)
{
m_rootEntity = hierarchyRoot;
if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority)
if (newHierarchyRoot)
{
NetworkHierarchyChildComponentController* controller = static_cast<NetworkHierarchyChildComponentController*>(GetController());
if (hierarchyRoot)
if (m_rootEntity != newHierarchyRoot)
{
const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(hierarchyRoot->GetId());
controller->SetHierarchyRoot(netRootId);
}
else
{
controller->SetHierarchyRoot(InvalidNetEntityId);
m_rootEntity = newHierarchyRoot;
if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority)
{
NetworkHierarchyRootComponentController* controller = static_cast<NetworkHierarchyRootComponentController*>(GetController());
const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(m_rootEntity->GetId());
controller->SetHierarchyRoot(netRootId);
}
GetNetBindComponent()->SetOwningConnectionId(m_rootEntity->FindComponent<NetBindComponent>()->GetOwningConnectionId());
m_networkHierarchyChangedEvent.Signal(m_rootEntity->GetId());
}
}
if (m_rootEntity == nullptr)
else if ((previousHierarchyRoot && m_rootEntity == previousHierarchyRoot) || !previousHierarchyRoot)
{
m_rootEntity = nullptr;
if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority)
{
NetworkHierarchyRootComponentController* controller = static_cast<NetworkHierarchyRootComponentController*>(GetController());
controller->SetHierarchyRoot(InvalidNetEntityId);
}
GetNetBindComponent()->SetOwningConnectionId(m_previousOwningConnectionId);
m_networkHierarchyLeaveEvent.Signal();
// We lost the parent hierarchical entity, so as a root we need to re-build our own hierarchy.
RebuildHierarchy();
}
}
void NetworkHierarchyRootComponent::SetOwningConnectionId(AzNetworking::ConnectionId connectionId)
{
NetworkHierarchyRootComponentBase::SetOwningConnectionId(connectionId);
if (IsHierarchicalChild() == false)
{
m_previousOwningConnectionId = connectionId;
}
}
NetworkHierarchyRootComponentController::NetworkHierarchyRootComponentController(NetworkHierarchyRootComponent& parent)
: NetworkHierarchyRootComponentControllerBase(parent)
{
@@ -370,7 +391,7 @@ namespace Multiplayer
void NetworkHierarchyRootComponentController::CreateInput(Multiplayer::NetworkInput& input, float deltaTime)
{
NetworkHierarchyRootComponent& component = GetParent();
if(!component.IsHierarchicalRoot())
if (!component.IsHierarchicalRoot())
{
return;
}
@@ -386,7 +407,7 @@ namespace Multiplayer
for (AZ::Entity* child : entities)
{
if(child == component.GetEntity())
if (child == component.GetEntity())
{
continue; // Avoid infinite recursion
}