123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /*
- * 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
- *
- */
- #include <AzCore/Serialization/EditContext.h>
- #include <AzFramework/Components/TransformComponent.h>
- #include <Multiplayer/IMultiplayer.h>
- #include <Multiplayer/Components/NetBindComponent.h>
- #include <Multiplayer/Components/NetworkHierarchyBus.h>
- #include <Multiplayer/Components/NetworkHierarchyChildComponent.h>
- #include <Multiplayer/Components/NetworkHierarchyRootComponent.h>
- namespace Multiplayer
- {
- void NetworkHierarchyChildComponent::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
- if (serializeContext)
- {
- serializeContext->Class<NetworkHierarchyChildComponent, NetworkHierarchyChildComponentBase>()
- ->Version(1);
- if (AZ::EditContext* editContext = serializeContext->GetEditContext())
- {
- editContext->Class<NetworkHierarchyChildComponent>(
- "Network Hierarchy Child", "Declares a network dependency on the root of this hierarchy.")
- ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
- ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer")
- ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
- ;
- }
- }
- NetworkHierarchyChildComponentBase::Reflect(context);
- }
- void NetworkHierarchyChildComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
- {
- required.push_back(AZ_CRC_CE("NetworkTransformComponent"));
- }
- void NetworkHierarchyChildComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
- {
- provided.push_back(AZ_CRC_CE("NetworkHierarchyChildComponent"));
- provided.push_back(AZ_CRC_CE("MultiplayerInputDriver"));
- }
- void NetworkHierarchyChildComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
- {
- incompatible.push_back(AZ_CRC_CE("NetworkHierarchyChildComponent"));
- incompatible.push_back(AZ_CRC_CE("NetworkHierarchyRootComponent"));
- }
- NetworkHierarchyChildComponent::NetworkHierarchyChildComponent()
- : m_childChangedHandler([this](AZ::ChildChangeType type, AZ::EntityId child) { OnChildChanged(type, child); })
- , m_hierarchyRootNetIdChanged([this](NetEntityId rootNetId) {OnHierarchyRootNetIdChanged(rootNetId); })
- {
- }
- void NetworkHierarchyChildComponent::OnInit()
- {
- }
- void NetworkHierarchyChildComponent::OnActivate([[maybe_unused]] EntityIsMigrating entityIsMigrating)
- {
- m_isHierarchyEnabled = true;
- HierarchyRootAddEvent(m_hierarchyRootNetIdChanged);
- NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId());
- if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent<AzFramework::TransformComponent>())
- {
- transformComponent->BindChildChangedEventHandler(m_childChangedHandler);
- }
- }
- void NetworkHierarchyChildComponent::OnDeactivate([[maybe_unused]] EntityIsMigrating entityIsMigrating)
- {
- m_isHierarchyEnabled = false;
- if (m_rootEntity)
- {
- if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent<NetworkHierarchyRootComponent>())
- {
- root->RebuildHierarchy();
- }
- }
- NotifyChildrenHierarchyDisbanded();
- NetworkHierarchyRequestBus::Handler::BusDisconnect();
- }
- bool NetworkHierarchyChildComponent::IsHierarchyEnabled() const
- {
- return m_isHierarchyEnabled;
- }
- bool NetworkHierarchyChildComponent::IsHierarchicalChild() const
- {
- return GetHierarchyRoot() != InvalidNetEntityId;
- }
- AZ::Entity* NetworkHierarchyChildComponent::GetHierarchicalRoot() const
- {
- return m_rootEntity;
- }
- AZStd::vector<AZ::Entity*> NetworkHierarchyChildComponent::GetHierarchicalEntities() const
- {
- if (m_rootEntity)
- {
- return m_rootEntity->FindComponent<NetworkHierarchyRootComponent>()->GetHierarchicalEntities();
- }
- return {};
- }
- void NetworkHierarchyChildComponent::BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler)
- {
- handler.Connect(m_networkHierarchyChangedEvent);
- }
- void NetworkHierarchyChildComponent::BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler)
- {
- handler.Connect(m_networkHierarchyLeaveEvent);
- }
- void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* previousHierarchyRoot, AZ::Entity* newHierarchyRoot)
- {
- if (newHierarchyRoot)
- {
- if (m_rootEntity != newHierarchyRoot)
- {
- m_rootEntity = newHierarchyRoot;
- const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(m_rootEntity->GetId());
- TrySetControllerRoot(netRootId);
- GetNetBindComponent()->SetOwningConnectionId(m_rootEntity->FindComponent<NetBindComponent>()->GetOwningConnectionId());
- m_networkHierarchyChangedEvent.Signal(m_rootEntity->GetId());
- }
- }
- else if ((previousHierarchyRoot && m_rootEntity == previousHierarchyRoot) || !previousHierarchyRoot)
- {
- m_rootEntity = nullptr;
- TrySetControllerRoot(InvalidNetEntityId);
- GetNetBindComponent()->SetOwningConnectionId(m_previousOwningConnectionId);
- m_networkHierarchyLeaveEvent.Signal();
- NotifyChildrenHierarchyDisbanded();
- }
- }
- void NetworkHierarchyChildComponent::TrySetControllerRoot([[maybe_unused]] const NetEntityId rootNetId)
- {
- #if AZ_TRAIT_SERVER
- if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority)
- {
- NetworkHierarchyChildComponentController* controller = static_cast<NetworkHierarchyChildComponentController*>(GetController());
- controller->SetHierarchyRoot(rootNetId);
- }
- #endif
- }
- void NetworkHierarchyChildComponent::SetOwningConnectionId(AzNetworking::ConnectionId connectionId)
- {
- NetworkHierarchyChildComponentBase::SetOwningConnectionId(connectionId);
- if (IsHierarchicalChild() == false)
- {
- m_previousOwningConnectionId = connectionId;
- }
- }
- void NetworkHierarchyChildComponent::OnChildChanged([[maybe_unused]] AZ::ChildChangeType type, [[maybe_unused]] AZ::EntityId child)
- {
- if (m_rootEntity)
- {
- if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent<NetworkHierarchyRootComponent>())
- {
- root->RebuildHierarchy();
- }
- }
- }
- void NetworkHierarchyChildComponent::OnHierarchyRootNetIdChanged(NetEntityId rootNetId)
- {
- ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(rootNetId);
- if (rootHandle.Exists())
- {
- AZ::Entity* newRoot = rootHandle.GetEntity();
- 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;
- }
- }
- void NetworkHierarchyChildComponent::NotifyChildrenHierarchyDisbanded()
- {
- AZ::ComponentApplicationRequests* componentApplication = AZ::Interface<AZ::ComponentApplicationRequests>::Get();
- AZStd::vector<AZ::EntityId> allChildren;
- AZ::TransformBus::EventResult(allChildren, GetEntityId(), &AZ::TransformBus::Events::GetChildren);
- for (const AZ::EntityId& childEntityId : allChildren)
- {
- if (const AZ::Entity* childEntity = componentApplication->FindEntity(childEntityId))
- {
- if (auto* hierarchyChildComponent = childEntity->FindComponent<NetworkHierarchyChildComponent>())
- {
- hierarchyChildComponent->SetTopLevelHierarchyRootEntity(nullptr, nullptr);
- }
- else if (auto* hierarchyRootComponent = childEntity->FindComponent<NetworkHierarchyRootComponent>())
- {
- hierarchyRootComponent->SetTopLevelHierarchyRootEntity(nullptr, nullptr);
- }
- }
- }
- }
- }
|