diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/EntityDomains/IEntityDomain.h b/Gems/Multiplayer/Code/Include/Multiplayer/EntityDomains/IEntityDomain.h index fc41a9b4d0..4b1bbbdba8 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/EntityDomains/IEntityDomain.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/EntityDomains/IEntityDomain.h @@ -17,8 +17,6 @@ namespace Multiplayer class IEntityDomain { public: - using EntitiesNotInDomain = AZStd::unordered_set; - virtual ~IEntityDomain() = default; //! For domains that operate on a region of space, this sets the area the domain is responsible for. @@ -34,12 +32,10 @@ namespace Multiplayer //! @return false if this entity should not belong to the entity manger, true if it could be owned by the entity manager virtual bool IsInDomain(const ConstNetworkEntityHandle& entityHandle) const = 0; - //! Enable Entity Domain Exit Tracking for entities on the host. - //! @param ownedEntitySet the set of entities to activate tracking for - virtual void ActivateTracking(const INetworkEntityManager::OwnedEntitySet& ownedEntitySet) = 0; - - //! Return the set of netbound entities not included in this domain. - virtual const EntitiesNotInDomain& RetrieveEntitiesNotInDomain() const = 0; + //! This method will be invoked whenever we unexpectedly lose the authoritative entity replicator for an entity. + //! This gives our entity domain a chance to determine whether or not it should assume authority in this instance. + //! @param entityHandle the network entity handle of the entity that has lost it's authoritative replicator + virtual void HandleLossOfAuthoritativeReplicator(const ConstNetworkEntityHandle& entityHandle) = 0; //! Debug draw to visualize host entity domains. virtual void DebugDraw() const = 0; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h index 43915127ed..8c16176736 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h @@ -26,6 +26,7 @@ namespace Multiplayer using EntityExitDomainEvent = AZ::Event; using ControllersActivatedEvent = AZ::Event; using ControllersDeactivatedEvent = AZ::Event; + using NetEntityIdSet = AZStd::unordered_set; //! @class INetworkEntityManager //! @brief The interface for managing all networked entities. @@ -34,18 +35,17 @@ namespace Multiplayer public: AZ_RTTI(INetworkEntityManager, "{109759DE-9492-439C-A0B1-AE46E6FD029C}"); - using OwnedEntitySet = AZStd::unordered_set; using EntityList = AZStd::vector; virtual ~INetworkEntityManager() = default; - //! Configures the NetworkEntityManager to operate as an authoritative host. - //! @param hostId the hostId of this NetworkEntityManager + //! Configures the NetworkEntityManager. + //! @param hostId the hostId of this NetworkEntityManager (invalid for clients) //! @param entityDomain the entity domain used to determine which entities this manager has authority over virtual void Initialize(const HostId& hostId, AZStd::unique_ptr entityDomain) = 0; - //! Returns whether or not the network entity manager has been initialized to host. - //! @return boolean true if this network entity manager has been intialized to host + //! Returns whether or not the network entity manager has been initialized. + //! @return boolean true if this network entity manager has been intialized virtual bool IsInitialized() const = 0; //! Returns the entity domain associated with this network entity manager, this will be nullptr on clients. @@ -181,6 +181,19 @@ namespace Multiplayer //! @param entityRpcMessage the local rpc message to handle virtual void HandleLocalRpcMessage(NetworkEntityRpcMessage& message) = 0; + //! Handles a set of entities transitioning between entity domains. + //! @param entitiesNotInDomain the set of entities that are no longer contained within our entity domain + virtual void HandleEntitiesExitDomain(const NetEntityIdSet& entitiesNotInDomain) = 0; + + //! Forcibly assumes authoritative control over the given entity. + //! This should only be used in the event of the unexpected loss of the previous authority, any other usage could corrupt the simulation. + //! @param entityHandle the entity to forcibly assume authoritative control over + virtual void ForceAssumeAuthority(const ConstNetworkEntityHandle& entityHandle) = 0; + + //! Overrides the default timeout time used during entity migrations. + //! @param timeoutTimeMs the timeout time to use in milliseconds + virtual void SetMigrateTimeoutTimeMs(AZ::TimeMs timeoutTimeMs) = 0; + //! Visualization of network entity manager state. virtual void DebugDraw() const = 0; }; diff --git a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp index cc71000d33..ceb9412408 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetBindComponent.cpp @@ -317,7 +317,7 @@ namespace Multiplayer return false; } - bool NetBindComponent::HandlePropertyChangeMessage([[maybe_unused]] AzNetworking::ISerializer& serializer, [[maybe_unused]] bool notifyChanges) + bool NetBindComponent::HandlePropertyChangeMessage(AzNetworking::ISerializer& serializer, bool notifyChanges) { const NetEntityRole netEntityRole = m_netEntityRole; ReplicationRecord replicationRecord(netEntityRole); @@ -492,7 +492,7 @@ namespace Multiplayer void NetBindComponent::FillTotalReplicationRecord(ReplicationRecord& replicationRecord) const { replicationRecord.Append(m_totalRecord); - // if we have any outstanding changes yet to be logged, grab those as well + // If we have any outstanding changes yet to be logged, grab those as well if (m_currentRecord.HasChanges()) { replicationRecord.Append(m_currentRecord); diff --git a/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.cpp b/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.cpp index 9d53990fb4..59e2afc638 100644 --- a/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.cpp +++ b/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.cpp @@ -26,14 +26,9 @@ namespace Multiplayer return true; } - void FullOwnershipEntityDomain::ActivateTracking([[maybe_unused]] const INetworkEntityManager::OwnedEntitySet& ownedEntitySet) + void FullOwnershipEntityDomain::HandleLossOfAuthoritativeReplicator([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle) { - ; - } - - const IEntityDomain::EntitiesNotInDomain& FullOwnershipEntityDomain::RetrieveEntitiesNotInDomain() const - { - return m_entitiesNotInDomain; + AZ_Assert(false, "FullOwnershipEntityDomain has authoritative control over all entities, something unexpected has happened"); } void FullOwnershipEntityDomain::DebugDraw() const diff --git a/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.h b/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.h index ae80c16ab8..203d9579ea 100644 --- a/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.h +++ b/Gems/Multiplayer/Code/Source/EntityDomains/FullOwnershipEntityDomain.h @@ -24,12 +24,8 @@ namespace Multiplayer void SetAabb(const AZ::Aabb& aabb) override; const AZ::Aabb& GetAabb() const override; bool IsInDomain(const ConstNetworkEntityHandle& entityHandle) const override; - void ActivateTracking(const INetworkEntityManager::OwnedEntitySet& ownedEntitySet) override; - const EntitiesNotInDomain& RetrieveEntitiesNotInDomain() const override; + void HandleLossOfAuthoritativeReplicator(const ConstNetworkEntityHandle& entityHandle) override; void DebugDraw() const override; //! @} - - private: - EntitiesNotInDomain m_entitiesNotInDomain; }; } diff --git a/Gems/Multiplayer/Code/Source/EntityDomains/NullEntityDomain.cpp b/Gems/Multiplayer/Code/Source/EntityDomains/NullEntityDomain.cpp new file mode 100644 index 0000000000..21d6abcb5a --- /dev/null +++ b/Gems/Multiplayer/Code/Source/EntityDomains/NullEntityDomain.cpp @@ -0,0 +1,41 @@ +/* + * 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 +#include +#include + +namespace Multiplayer +{ + void NullEntityDomain::SetAabb([[maybe_unused]] const AZ::Aabb& aabb) + { + ; // Do nothing, by definition we own everything + } + + const AZ::Aabb& NullEntityDomain::GetAabb() const + { + static AZ::Aabb nullAabb = AZ::Aabb::CreateNull(); + return nullAabb; + } + + bool NullEntityDomain::IsInDomain([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle) const + { + return false; + } + + void NullEntityDomain::HandleLossOfAuthoritativeReplicator([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle) + { + AZLOG_ERROR("Timed out entity id %llu during migration, marking for removal", aznumeric_cast(entityHandle.GetNetEntityId())); + GetNetworkEntityManager()->MarkForRemoval(entityHandle); + } + + void NullEntityDomain::DebugDraw() const + { + ; + } +} diff --git a/Gems/Multiplayer/Code/Source/EntityDomains/NullEntityDomain.h b/Gems/Multiplayer/Code/Source/EntityDomains/NullEntityDomain.h new file mode 100644 index 0000000000..247d82b366 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/EntityDomains/NullEntityDomain.h @@ -0,0 +1,31 @@ +/* + * 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 + * + */ + +#pragma once + +#include + +namespace Multiplayer +{ + class NullEntityDomain + : public IEntityDomain + { + public: + NullEntityDomain() = default; + NullEntityDomain(const NullEntityDomain& rhs) = default; + + //! IEntityDomain overrides. + //! @{ + void SetAabb(const AZ::Aabb& aabb) override; + const AZ::Aabb& GetAabb() const override; + bool IsInDomain(const ConstNetworkEntityHandle& entityHandle) const override; + void HandleLossOfAuthoritativeReplicator(const ConstNetworkEntityHandle& entityHandle) override; + void DebugDraw() const override; + //! @} + }; +} diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 0bf5cea64b..1bc3404292 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -832,18 +833,21 @@ namespace Multiplayer if (multiplayerType == MultiplayerAgentType::ClientServer || multiplayerType == MultiplayerAgentType::DedicatedServer) { m_spawnNetboundEntities = true; - m_initEvent.Signal(m_networkInterface); - + m_initEvent.Signal(m_networkInterface); //< Note! This might initialize our network entity manager for us if (!m_networkEntityManager.IsInitialized()) { - // Set up a full ownership domain if we didn't construct a domain during the initialize event const AZ::CVarFixedString serverAddr = cl_serveraddr; const uint16_t serverPort = cl_serverport; const AzNetworking::ProtocolType serverProtocol = sv_protocol; const AzNetworking::IpAddress hostId = AzNetworking::IpAddress(serverAddr.c_str(), serverPort, serverProtocol); + // Set up a full ownership domain if we didn't construct a domain during the initialize event m_networkEntityManager.Initialize(hostId, AZStd::make_unique()); } } + else if (multiplayerType == MultiplayerAgentType::Client) + { + m_networkEntityManager.Initialize(AzNetworking::IpAddress(), AZStd::make_unique()); + } } m_agentType = multiplayerType; diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.cpp index 7b6e8476e7..9f66bbee9e 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -17,14 +18,20 @@ namespace Multiplayer { - AZ_CVAR(AZ::TimeMs, net_EntityMigrationTimeoutMs, AZ::TimeMs{ 1000 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Time to wait for a new authority to attach to an entity before we delete the entity"); + AZ_CVAR(AZ::TimeMs, net_DefaultEntityMigrationTimeoutMs, AZ::TimeMs{ 1000 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Time to wait for a new authority to attach to an entity before we delete the entity"); NetworkEntityAuthorityTracker::NetworkEntityAuthorityTracker(INetworkEntityManager& networkEntityManager) : m_networkEntityManager(networkEntityManager) + , m_timeoutTimeMs(net_DefaultEntityMigrationTimeoutMs) { ; } + void NetworkEntityAuthorityTracker::SetTimeoutTimeMs(AZ::TimeMs timeoutTimeMs) + { + m_timeoutTimeMs = timeoutTimeMs; + } + bool NetworkEntityAuthorityTracker::AddEntityAuthorityManager(ConstNetworkEntityHandle entityHandle, const HostId& newOwner) { bool ret = false; @@ -92,7 +99,7 @@ namespace Multiplayer "Trying to add something twice to the timeout map, this is unexpected" ); m_timeoutDataMap.insert(entityHandle.GetNetEntityId()); - AZ::Interface::Get()->AddCallback([this, netEntityId = entityHandle.GetNetEntityId(), previousOwner] + AZ::Interface::Get()->AddCallback([this, netEntityId = entityHandle.GetNetEntityId()] { auto timeoutData = m_timeoutDataMap.find(netEntityId); if (timeoutData != m_timeoutDataMap.end()) @@ -109,19 +116,13 @@ namespace Multiplayer } if (networkRole != NetEntityRole::Authority) { - AZLOG_ERROR - ( - "Timed out entity id %llu during migration previous owner %s, removing it", - aznumeric_cast(entityHandle.GetNetEntityId()), - previousOwner.GetString().c_str() - ); - m_networkEntityManager.MarkForRemoval(entityHandle); + m_networkEntityManager.GetEntityDomain()->HandleLossOfAuthoritativeReplicator(entityHandle); } } } }, AZ::Name("Entity authority removal functor"), - net_EntityMigrationTimeoutMs + m_timeoutTimeMs ); } else diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.h index c2e330ab4d..edb1b26ca8 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityAuthorityTracker.h @@ -23,6 +23,7 @@ namespace Multiplayer public: NetworkEntityAuthorityTracker(INetworkEntityManager& networkEntityManager); + void SetTimeoutTimeMs(AZ::TimeMs timeoutTimeMs); bool DoesEntityHaveOwner(ConstNetworkEntityHandle entityHandle) const; bool AddEntityAuthorityManager(ConstNetworkEntityHandle entityHandle, const HostId& newOwner); void RemoveEntityAuthorityManager(ConstNetworkEntityHandle entityHandle, const HostId& previousOwner); @@ -37,5 +38,7 @@ namespace Multiplayer TimeoutDataMap m_timeoutDataMap; EntityAuthorityMap m_entityAuthorityMap; INetworkEntityManager& m_networkEntityManager; + + AZ::TimeMs m_timeoutTimeMs = AZ::TimeMs{ 0 }; }; } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index c7582af83f..b178ebeb02 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -28,12 +28,10 @@ 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")) { AZ::Interface::Register(this); AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); @@ -63,8 +61,6 @@ namespace Multiplayer } m_entityDomain = AZStd::move(entityDomain); - m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true); - m_entityDomain->ActivateTracking(m_ownedEntities); } bool NetworkEntityManager::IsInitialized() const @@ -231,6 +227,74 @@ namespace Multiplayer m_localDeferredRpcMessages.emplace_back(AZStd::move(message)); } + void NetworkEntityManager::HandleEntitiesExitDomain(const NetEntityIdSet& entitiesNotInDomain) + { + for (NetEntityId exitingId : entitiesNotInDomain) + { + bool safeToExit = true; + NetworkEntityHandle entityHandle = m_networkEntityTracker.Get(exitingId); + + // We need special handling for the NetworkHierarchy as well, since related entities need to be migrated together + NetworkHierarchyRootComponentController* hierarchyRootController = entityHandle.FindController(); + NetworkHierarchyChildComponentController* hierarchyChildController = entityHandle.FindController(); + + // Find the root entity + AZ::Entity* hierarchyRootEntity = nullptr; + if (hierarchyRootController) + { + hierarchyRootEntity = hierarchyRootController->GetParent().GetHierarchicalRoot(); + } + else if (hierarchyChildController) + { + hierarchyRootEntity = hierarchyChildController->GetParent().GetHierarchicalRoot(); + } + + if (hierarchyRootEntity) + { + NetEntityId rootNetId = GetNetEntityIdById(hierarchyRootEntity->GetId()); + ConstNetworkEntityHandle rootEntityHandle = GetEntity(rootNetId); + + // Check if the root entity is still tracked by this authority + if (rootEntityHandle.Exists() && rootEntityHandle.GetNetBindComponent()->HasController()) + { + safeToExit = false; + } + } + + // Validate that we aren't already planning to remove this entity + if (safeToExit) + { + for (auto remoteEntityId : m_removeList) + { + if (remoteEntityId == remoteEntityId) + { + safeToExit = false; + } + } + } + + if (safeToExit) + { + // Tell all the attached replicators for this entity that it's exited the domain + m_entityExitDomainEvent.Signal(entityHandle); + } + } + } + + void NetworkEntityManager::ForceAssumeAuthority(const ConstNetworkEntityHandle& entityHandle) + { + NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent(); + if (netBindComponent != nullptr) + { + netBindComponent->ConstructControllers(); + } + } + + void NetworkEntityManager::SetMigrateTimeoutTimeMs(AZ::TimeMs timeoutTimeMs) + { + m_networkEntityAuthorityTracker.SetTimeoutTimeMs(timeoutTimeMs); + } + void NetworkEntityManager::DebugDraw() const { AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; @@ -243,7 +307,7 @@ namespace Multiplayer NetBindComponent* netBindComponent = m_networkEntityTracker.GetNetBindComponent(entity); AZ::Aabb entityBounds = AZ::Interface::Get()->GetEntityWorldBoundsUnion(entity->GetId()); entityBounds.Expand(AZ::Vector3(0.01f)); - if (netBindComponent->GetNetEntityRole() == NetEntityRole::Authority) + if ((netBindComponent != nullptr) && netBindComponent->GetNetEntityRole() == NetEntityRole::Authority) { debugDisplay->SetColor(AZ::Colors::Black); debugDisplay->SetAlpha(0.5f); @@ -277,77 +341,11 @@ namespace Multiplayer m_localDeferredRpcMessages.clear(); } - void NetworkEntityManager::UpdateEntityDomain() - { - if (m_entityDomain == nullptr) - { - return; - } - - const IEntityDomain::EntitiesNotInDomain& entitiesNotInDomain = m_entityDomain->RetrieveEntitiesNotInDomain(); - for (NetEntityId exitingId : entitiesNotInDomain) - { - OnEntityExitDomain(exitingId); - } - } - - void NetworkEntityManager::OnEntityExitDomain(NetEntityId entityId) - { - bool safeToExit = true; - NetworkEntityHandle entityHandle = m_networkEntityTracker.Get(entityId); - - // We also need special handling for the NetworkHierarchy as well, since related entities need to be migrated together - NetworkHierarchyRootComponentController* hierarchyRootController = entityHandle.FindController(); - NetworkHierarchyChildComponentController* hierarchyChildController = entityHandle.FindController(); - - // Find the root entity - AZ::Entity* hierarchyRootEntity = nullptr; - if (hierarchyRootController) - { - hierarchyRootEntity = hierarchyRootController->GetParent().GetHierarchicalRoot(); - } - else if (hierarchyChildController) - { - hierarchyRootEntity = hierarchyChildController->GetParent().GetHierarchicalRoot(); - } - - if (hierarchyRootEntity) - { - NetEntityId rootNetId = GetNetEntityIdById(hierarchyRootEntity->GetId()); - ConstNetworkEntityHandle rootEntityHandle = GetEntity(rootNetId); - - // Check if the root entity is still tracked by this authority - if (rootEntityHandle.Exists() && rootEntityHandle.GetNetBindComponent()->HasController()) - { - safeToExit = false; - } - } - - // Validate that we aren't already planning to remove this entity - if (safeToExit) - { - for (auto remoteEntityId : m_removeList) - { - if (remoteEntityId == remoteEntityId) - { - safeToExit = false; - } - } - } - - if (safeToExit) - { - m_entityExitDomainEvent.Signal(entityHandle); - } - } - void NetworkEntityManager::Reset() { m_multiplayerComponentRegistry.Reset(); m_removeList.clear(); m_entityDomain = nullptr; - m_updateEntityDomainEvent.RemoveFromQueue(); - m_ownedEntities.clear(); m_entityExitDomainEvent.DisconnectAllHandlers(); m_onEntityMarkedDirty.DisconnectAllHandlers(); m_onEntityNotifyChanges.DisconnectAllHandlers(); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index 133c35dce0..7c6fdd94f9 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -79,12 +79,13 @@ namespace Multiplayer void NotifyControllersActivated(const ConstNetworkEntityHandle& entityHandle, EntityIsMigrating entityIsMigrating) override; void NotifyControllersDeactivated(const ConstNetworkEntityHandle& entityHandle, EntityIsMigrating entityIsMigrating) override; void HandleLocalRpcMessage(NetworkEntityRpcMessage& message) override; + void HandleEntitiesExitDomain(const NetEntityIdSet& entitiesNotInDomain) override; + void ForceAssumeAuthority(const ConstNetworkEntityHandle& entityHandle) override; + void SetMigrateTimeoutTimeMs(AZ::TimeMs timeoutTimeMs) override; void DebugDraw() const override; //! @} void DispatchLocalDeferredRpcMessages(); - void UpdateEntityDomain(); - void OnEntityExitDomain(NetEntityId entityId); //! RootSpawnableNotificationBus //! @{ @@ -106,9 +107,6 @@ namespace Multiplayer AZ::ScheduledEvent m_removeEntitiesEvent; AZStd::vector m_removeList; AZStd::unique_ptr m_entityDomain; - AZ::ScheduledEvent m_updateEntityDomainEvent; - - OwnedEntitySet m_ownedEntities; EntityExitDomainEvent m_entityExitDomainEvent; AZ::Event<> m_onEntityMarkedDirty; diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index a799278203..d417304877 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -94,6 +94,8 @@ set(FILES Source/Editor/MultiplayerEditorConnection.h Source/EntityDomains/FullOwnershipEntityDomain.cpp Source/EntityDomains/FullOwnershipEntityDomain.h + Source/EntityDomains/NullEntityDomain.cpp + Source/EntityDomains/NullEntityDomain.h Source/MultiplayerStats.cpp Source/MultiplayerSystemComponent.cpp Source/MultiplayerSystemComponent.h