NetworkEntityAuthorityTracker.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Source/NetworkEntity/NetworkEntityAuthorityTracker.h>
  9. #include <Multiplayer/Components/NetBindComponent.h>
  10. #include <Multiplayer/NetworkEntity/INetworkEntityManager.h>
  11. #include <Multiplayer/EntityDomains/IEntityDomain.h>
  12. #include <AzCore/Console/IConsole.h>
  13. #include <AzCore/Console/ILogger.h>
  14. #include <AzCore/EBus/IEventScheduler.h>
  15. #include <AzNetworking/Utilities/NetworkCommon.h>
  16. namespace Multiplayer
  17. {
  18. 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");
  19. NetworkEntityAuthorityTracker::NetworkEntityAuthorityTracker(INetworkEntityManager& networkEntityManager)
  20. : m_networkEntityManager(networkEntityManager)
  21. , m_timeoutTimeMs(net_DefaultEntityMigrationTimeoutMs)
  22. {
  23. ;
  24. }
  25. void NetworkEntityAuthorityTracker::SetTimeoutTimeMs(AZ::TimeMs timeoutTimeMs)
  26. {
  27. m_timeoutTimeMs = timeoutTimeMs;
  28. }
  29. bool NetworkEntityAuthorityTracker::AddEntityAuthorityManager(ConstNetworkEntityHandle entityHandle, const HostId& newOwner)
  30. {
  31. bool ret = false;
  32. auto timeoutData = m_timedOutNetEntityIds.find(entityHandle.GetNetEntityId());
  33. if (timeoutData != m_timedOutNetEntityIds.end())
  34. {
  35. AZLOG
  36. (
  37. NET_AuthTracker,
  38. "AuthTracker: Removing timeout for networkEntityId %llu, new owner is %s",
  39. aznumeric_cast<AZ::u64>(entityHandle.GetNetEntityId()),
  40. newOwner.GetString().c_str()
  41. );
  42. m_timedOutNetEntityIds.erase(timeoutData);
  43. ret = true;
  44. }
  45. AZLOG
  46. (
  47. NET_AuthTracker,
  48. "AuthTracker: Assigning networkEntityId %llu to %s",
  49. aznumeric_cast<AZ::u64>(entityHandle.GetNetEntityId()),
  50. newOwner.GetString().c_str()
  51. );
  52. m_entityAuthorityMap[entityHandle.GetNetEntityId()].push_back(newOwner);
  53. return ret;
  54. }
  55. void NetworkEntityAuthorityTracker::RemoveEntityAuthorityManager(ConstNetworkEntityHandle entityHandle, const HostId& previousOwner)
  56. {
  57. auto mapIter = m_entityAuthorityMap.find(entityHandle.GetNetEntityId());
  58. if (mapIter != m_entityAuthorityMap.end())
  59. {
  60. auto& authorityStack = mapIter->second;
  61. for (auto stackIter = authorityStack.begin(); stackIter != authorityStack.end();)
  62. {
  63. if (*stackIter == previousOwner)
  64. {
  65. stackIter = authorityStack.erase(stackIter);
  66. }
  67. else
  68. {
  69. ++stackIter;
  70. }
  71. }
  72. AZLOG(NET_AuthTracker, "AuthTracker: Removing networkEntityId %llu from %s", aznumeric_cast<AZ::u64>(entityHandle.GetNetEntityId()), previousOwner.GetString().c_str());
  73. if (entityHandle.GetEntity())
  74. {
  75. if (authorityStack.empty())
  76. {
  77. m_entityAuthorityMap.erase(entityHandle.GetNetEntityId());
  78. NetEntityRole networkRole = NetEntityRole::InvalidRole;
  79. NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
  80. if (netBindComponent != nullptr)
  81. {
  82. networkRole = netBindComponent->GetNetEntityRole();
  83. }
  84. if (networkRole != NetEntityRole::Autonomous)
  85. {
  86. AZ_Assert
  87. (
  88. m_timedOutNetEntityIds.find(entityHandle.GetNetEntityId()) == m_timedOutNetEntityIds.end(),
  89. "Trying to add something twice to the timeout map, this is unexpected"
  90. );
  91. m_timedOutNetEntityIds.insert(entityHandle.GetNetEntityId());
  92. AZ::Interface<AZ::IEventScheduler>::Get()->AddCallback([this, netEntityId = entityHandle.GetNetEntityId()]
  93. {
  94. auto timeoutData = m_timedOutNetEntityIds.find(netEntityId);
  95. if (timeoutData != m_timedOutNetEntityIds.end())
  96. {
  97. m_timedOutNetEntityIds.erase(timeoutData);
  98. ConstNetworkEntityHandle entityHandle = m_networkEntityManager.GetEntity(netEntityId);
  99. if (entityHandle.GetEntity())
  100. {
  101. NetEntityRole networkRole = NetEntityRole::InvalidRole;
  102. NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
  103. if (netBindComponent != nullptr)
  104. {
  105. networkRole = netBindComponent->GetNetEntityRole();
  106. }
  107. if (networkRole != NetEntityRole::Authority)
  108. {
  109. m_networkEntityManager.GetEntityDomain()->HandleLossOfAuthoritativeReplicator(entityHandle);
  110. }
  111. }
  112. }
  113. },
  114. AZ::Name("Entity authority removal functor"),
  115. m_timeoutTimeMs
  116. );
  117. }
  118. else
  119. {
  120. AZLOG(NET_AuthTracker, "AuthTracker: Skipping timeout for Autonomous networkEntityId %llu", aznumeric_cast<AZ::u64>(entityHandle.GetNetEntityId()));
  121. }
  122. }
  123. }
  124. }
  125. else
  126. {
  127. AZLOG(NET_AuthTracker, "AuthTracker: Remove authority called on networkEntityId that was never added %llu", aznumeric_cast<AZ::u64>(entityHandle.GetNetEntityId()));
  128. AZ_Assert(false, "AuthTracker: Remove authority called on entity that was never added");
  129. }
  130. }
  131. HostId NetworkEntityAuthorityTracker::GetEntityAuthorityManager(ConstNetworkEntityHandle entityHandle) const
  132. {
  133. if (entityHandle.GetEntity())
  134. {
  135. NetEntityRole networkRole = NetEntityRole::InvalidRole;
  136. NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
  137. if (netBindComponent != nullptr)
  138. {
  139. networkRole = netBindComponent->GetNetEntityRole();
  140. }
  141. if (networkRole == NetEntityRole::Authority)
  142. {
  143. return m_networkEntityManager.GetHostId();
  144. }
  145. else
  146. {
  147. auto iter = m_entityAuthorityMap.find(entityHandle.GetNetEntityId());
  148. if (iter != m_entityAuthorityMap.end())
  149. {
  150. if (!iter->second.empty())
  151. {
  152. return iter->second.back();
  153. }
  154. }
  155. }
  156. }
  157. return InvalidHostId;
  158. }
  159. bool NetworkEntityAuthorityTracker::DoesEntityHaveOwner(ConstNetworkEntityHandle entityHandle) const
  160. {
  161. return InvalidHostId != GetEntityAuthorityManager(entityHandle);
  162. }
  163. }