CommonBenchmarkSetup.h 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  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. #pragma once
  9. #ifdef HAVE_BENCHMARK
  10. #include <CommonHierarchySetup.h>
  11. #include <AzCore/Component/Entity.h>
  12. #include <AzCore/Console/Console.h>
  13. #include <AzCore/Name/Name.h>
  14. #include <AzCore/Serialization/SerializeContext.h>
  15. #include <AzCore/UnitTest/Mocks/MockITime.h>
  16. #include <AzFramework/Components/TransformComponent.h>
  17. #include <benchmark/benchmark.h>
  18. #include <Multiplayer/Components/NetBindComponent.h>
  19. #include <Multiplayer/Components/NetworkHierarchyChildComponent.h>
  20. #include <Multiplayer/Components/NetworkHierarchyRootComponent.h>
  21. #include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.h>
  22. namespace Multiplayer
  23. {
  24. class BenchmarkComponentApplicationRequests : public AZ::ComponentApplicationRequests
  25. {
  26. public:
  27. void RegisterComponentDescriptor([[maybe_unused]] const AZ::ComponentDescriptor* descriptor) override {}
  28. void UnregisterComponentDescriptor([[maybe_unused]] const AZ::ComponentDescriptor* descriptor) override {}
  29. AZ::ComponentApplication* GetApplication() override { return {}; }
  30. void RegisterEntityAddedEventHandler([[maybe_unused]] AZ::Event<AZ::Entity*>::Handler& handler) override {}
  31. void RegisterEntityRemovedEventHandler([[maybe_unused]] AZ::Event<AZ::Entity*>::Handler& handler) override {}
  32. void RegisterEntityActivatedEventHandler([[maybe_unused]] AZ::Event<AZ::Entity*>::Handler& handler) override {}
  33. void RegisterEntityDeactivatedEventHandler([[maybe_unused]] AZ::Event<AZ::Entity*>::Handler& handler) override {}
  34. void SignalEntityActivated([[maybe_unused]] AZ::Entity* entity) override {}
  35. void SignalEntityDeactivated([[maybe_unused]] AZ::Entity* entity) override {}
  36. bool RemoveEntity([[maybe_unused]] AZ::Entity* entity) override { return {}; }
  37. bool DeleteEntity([[maybe_unused]] const AZ::EntityId& id) override { return {}; }
  38. void EnumerateEntities([[maybe_unused]] const EntityCallback& callback) override {}
  39. AZ::SerializeContext* GetSerializeContext() override { return {}; }
  40. AZ::BehaviorContext* GetBehaviorContext() override { return {}; }
  41. AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return {}; }
  42. const char* GetEngineRoot() const override { return {}; }
  43. const char* GetExecutableFolder() const override { return {}; }
  44. void QueryApplicationType([[maybe_unused]] AZ::ApplicationTypeQuery& appType) const override {}
  45. AZStd::map<AZ::EntityId, AZ::Entity*> m_entities;
  46. bool AddEntity(AZ::Entity* entity) override
  47. {
  48. m_entities[entity->GetId()] = entity;
  49. return true;
  50. }
  51. AZ::Entity* FindEntity(const AZ::EntityId& id) override
  52. {
  53. const auto iterator = m_entities.find(id);
  54. if (iterator != m_entities.end())
  55. {
  56. return iterator->second;
  57. }
  58. return nullptr;
  59. }
  60. };
  61. class BenchmarkConnectionListener : public AzNetworking::IConnectionListener
  62. {
  63. public:
  64. ConnectResult ValidateConnect([[maybe_unused]] const IpAddress& remoteAddress, [[maybe_unused]] const IPacketHeader& packetHeader, [[maybe_unused]] ISerializer& serializer) override
  65. {
  66. return {};
  67. }
  68. void OnConnect([[maybe_unused]] IConnection* connection) override
  69. {
  70. }
  71. PacketDispatchResult OnPacketReceived([[maybe_unused]] IConnection* connection, [[maybe_unused]] const IPacketHeader& packetHeader, [[maybe_unused]] ISerializer& serializer) override
  72. {
  73. return {};
  74. }
  75. void OnPacketLost([[maybe_unused]] IConnection* connection, [[maybe_unused]] PacketId packetId) override
  76. {
  77. }
  78. void OnDisconnect([[maybe_unused]] IConnection* connection, [[maybe_unused]] DisconnectReason reason, [[maybe_unused]] TerminationEndpoint endpoint) override
  79. {
  80. }
  81. };
  82. class BenchmarkNetworkTime : public Multiplayer::INetworkTime
  83. {
  84. public:
  85. bool IsTimeRewound() const override
  86. {
  87. return false;
  88. }
  89. HostFrameId GetHostFrameId() const override
  90. {
  91. return {};
  92. }
  93. HostFrameId GetUnalteredHostFrameId() const override
  94. {
  95. return {};
  96. }
  97. void IncrementHostFrameId() override
  98. {
  99. }
  100. AZ::TimeMs GetHostTimeMs() const override
  101. {
  102. return {};
  103. }
  104. float GetHostBlendFactor() const override
  105. {
  106. return 0;
  107. }
  108. AzNetworking::ConnectionId GetRewindingConnectionId() const override
  109. {
  110. return {};
  111. }
  112. void ForceSetTime([[maybe_unused]] HostFrameId frameId, [[maybe_unused]] AZ::TimeMs timeMs) override
  113. {
  114. }
  115. void SyncEntitiesToRewindState([[maybe_unused]] const AZ::Aabb& rewindVolume) override
  116. {
  117. }
  118. void ClearRewoundEntities() override
  119. {
  120. }
  121. void AlterTime([[maybe_unused]] HostFrameId frameId, [[maybe_unused]] AZ::TimeMs timeMs, [[maybe_unused]] float blendFactor, [[maybe_unused]] AzNetworking::ConnectionId rewindConnectionId) override
  122. {
  123. }
  124. };
  125. class BenchmarkMultiplayerConnection : public IConnection
  126. {
  127. public:
  128. BenchmarkMultiplayerConnection(ConnectionId connectionId, const IpAddress& address, [[maybe_unused]] ConnectionRole connectionRole)
  129. : IConnection(connectionId, address)
  130. {
  131. ;
  132. }
  133. ~BenchmarkMultiplayerConnection() override = default;
  134. bool SendReliablePacket([[maybe_unused]] const IPacket& packet) override
  135. {
  136. return false;
  137. }
  138. PacketId SendUnreliablePacket([[maybe_unused]] const IPacket& packet) override
  139. {
  140. return {};
  141. }
  142. bool WasPacketAcked([[maybe_unused]] PacketId packetId) const override
  143. {
  144. return false;
  145. }
  146. ConnectionState GetConnectionState() const override
  147. {
  148. return {};
  149. }
  150. ConnectionRole GetConnectionRole() const override
  151. {
  152. return {};
  153. }
  154. bool Disconnect([[maybe_unused]] DisconnectReason reason, [[maybe_unused]] TerminationEndpoint endpoint) override
  155. {
  156. return false;
  157. }
  158. void SetConnectionMtu([[maybe_unused]] uint32_t connectionMtu) override
  159. {
  160. }
  161. uint32_t GetConnectionMtu() const override
  162. {
  163. return 0;
  164. }
  165. };
  166. class BenchmarkNetworkEntityManager : public Multiplayer::INetworkEntityManager
  167. {
  168. public:
  169. BenchmarkNetworkEntityManager() : m_authorityTracker(*this) {}
  170. NetworkEntityTracker* GetNetworkEntityTracker() override { return &m_tracker; }
  171. NetworkEntityAuthorityTracker* GetNetworkEntityAuthorityTracker() override { return &m_authorityTracker; }
  172. MultiplayerComponentRegistry* GetMultiplayerComponentRegistry() override { return &m_multiplayerComponentRegistry; }
  173. const HostId& GetHostId() const override { return m_hostId; }
  174. mutable AZStd::map<NetEntityId, AZ::Entity*> m_networkEntityMap;
  175. NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) override
  176. {
  177. m_networkEntityMap[netEntityId] = entity;
  178. return NetworkEntityHandle(entity, &m_tracker);
  179. }
  180. void RemoveEntityFromEntityMap(NetEntityId netEntityId) override
  181. {
  182. m_networkEntityMap.erase(netEntityId);
  183. }
  184. ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const override
  185. {
  186. AZ::Entity* entity = m_networkEntityMap[netEntityId];
  187. return ConstNetworkEntityHandle(entity, &m_tracker);
  188. }
  189. NetEntityId GetNetEntityIdById(const AZ::EntityId& entityId) const override
  190. {
  191. for (const auto& pair : m_networkEntityMap)
  192. {
  193. if (pair.second->GetId() == entityId)
  194. {
  195. return pair.first;
  196. }
  197. }
  198. return InvalidNetEntityId;
  199. }
  200. void Initialize([[maybe_unused]] const HostId& hostId, [[maybe_unused]] AZStd::unique_ptr<IEntityDomain> entityDomain) override {}
  201. bool IsInitialized() const override { return false; }
  202. IEntityDomain* GetEntityDomain() const override { return nullptr; }
  203. EntityList CreateEntitiesImmediate(
  204. [[maybe_unused]] const PrefabEntityId& prefabEntryId,
  205. [[maybe_unused]] NetEntityRole netEntityRole,
  206. [[maybe_unused]] const AZ::Transform& transform,
  207. [[maybe_unused]] AutoActivate autoActivate) override {
  208. return {};
  209. }
  210. EntityList CreateEntitiesImmediate(
  211. [[maybe_unused]] const PrefabEntityId& prefabEntryId,
  212. [[maybe_unused]] NetEntityId netEntityId,
  213. [[maybe_unused]] NetEntityRole netEntityRole,
  214. [[maybe_unused]] AutoActivate autoActivate,
  215. [[maybe_unused]] const AZ::Transform& transform) override {
  216. return {};
  217. }
  218. [[nodiscard]] AZStd::unique_ptr<AzFramework::EntitySpawnTicket> RequestNetSpawnableInstantiation(
  219. [[maybe_unused]] const AZ::Data::Asset<AzFramework::Spawnable>& netSpawnable,
  220. [[maybe_unused]] const AZ::Transform& transform) override {
  221. return {};
  222. }
  223. void SetupNetEntity([[maybe_unused]] AZ::Entity* netEntity, [[maybe_unused]] PrefabEntityId prefabEntityId, [[maybe_unused]] NetEntityRole netEntityRole) override {}
  224. uint32_t GetEntityCount() const override {
  225. return 0;
  226. }
  227. void MarkForRemoval([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle) override {}
  228. bool IsMarkedForRemoval([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle) const override {
  229. return false;
  230. }
  231. void ClearEntityFromRemovalList([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle) override {}
  232. void ClearAllEntities() override {}
  233. void AddEntityMarkedDirtyHandler([[maybe_unused]] AZ::Event<>::Handler& entityMarkedDirtyHandle) override {}
  234. void AddEntityNotifyChangesHandler([[maybe_unused]] AZ::Event<>::Handler& entityNotifyChangesHandle) override {}
  235. void AddEntityExitDomainHandler([[maybe_unused]] EntityExitDomainEvent::Handler& entityExitDomainHandler) override {}
  236. void AddControllersActivatedHandler([[maybe_unused]] ControllersActivatedEvent::Handler& controllersActivatedHandler) override {}
  237. void AddControllersDeactivatedHandler([[maybe_unused]] ControllersDeactivatedEvent::Handler& controllersDeactivatedHandler) override {}
  238. void NotifyEntitiesDirtied() override {}
  239. void NotifyEntitiesChanged() override {}
  240. void NotifyControllersActivated([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle, [[maybe_unused]] EntityIsMigrating entityIsMigrating) override {}
  241. void NotifyControllersDeactivated([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle, [[maybe_unused]] EntityIsMigrating entityIsMigrating) override {}
  242. void HandleLocalRpcMessage([[maybe_unused]] NetworkEntityRpcMessage& message) override {}
  243. void HandleEntitiesExitDomain([[maybe_unused]] const NetEntityIdSet& entitiesNotInDomain) override {}
  244. void ForceAssumeAuthority([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle) override {}
  245. void MarkAlwaysRelevantToClients(const ConstNetworkEntityHandle&, bool) override {}
  246. void MarkAlwaysRelevantToServers(const ConstNetworkEntityHandle&, bool) override {}
  247. const NetEntityHandleSet& GetAlwaysRelevantToClientsSet() const override { static NetEntityHandleSet value; return value; }
  248. const NetEntityHandleSet& GetAlwaysRelevantToServersSet() const override { static NetEntityHandleSet value; return value; }
  249. void SetMigrateTimeoutTimeMs([[maybe_unused]] AZ::TimeMs timeoutTimeMs) override {}
  250. void DebugDraw() const override {}
  251. NetworkEntityTracker m_tracker;
  252. NetworkEntityAuthorityTracker m_authorityTracker;
  253. MultiplayerComponentRegistry m_multiplayerComponentRegistry;
  254. HostId m_hostId;
  255. };
  256. class BenchmarkMultiplayer : public Multiplayer::IMultiplayer
  257. {
  258. public:
  259. BenchmarkMultiplayer(BenchmarkNetworkEntityManager& manager) : m_manager(manager) {}
  260. MultiplayerAgentType GetAgentType() const override { return {}; }
  261. void InitializeMultiplayer([[maybe_unused]] MultiplayerAgentType state) override {}
  262. bool StartHosting([[maybe_unused]] uint16_t port, [[maybe_unused]] bool isDedicated) override { return {}; }
  263. bool Connect([[maybe_unused]] const AZStd::string& remoteAddress, [[maybe_unused]] uint16_t port) override { return {}; }
  264. void Terminate([[maybe_unused]] AzNetworking::DisconnectReason reason) override {}
  265. void AddNetworkInitHandler([[maybe_unused]] NetworkInitEvent::Handler& handler) override {}
  266. void AddEndpointDisconnectedHandler([[maybe_unused]] EndpointDisconnectedEvent::Handler& handler) override {}
  267. void AddConnectionAcquiredHandler([[maybe_unused]] ConnectionAcquiredEvent::Handler& handler) override {}
  268. void AddServerAcceptanceReceivedHandler([[maybe_unused]] ServerAcceptanceReceivedEvent::Handler& handler) override {}
  269. void AddSessionInitHandler([[maybe_unused]] SessionInitEvent::Handler& handler) override {}
  270. void AddSessionShutdownHandler([[maybe_unused]] SessionShutdownEvent::Handler& handler) override {}
  271. void AddLevelLoadBlockedHandler([[maybe_unused]] LevelLoadBlockedEvent::Handler& handler) override {}
  272. void AddNoServerLevelLoadedHandler([[maybe_unused]] NoServerLevelLoadedEvent::Handler& handler) override {}
  273. void AddVersionMismatchHandler([[maybe_unused]] VersionMismatchEvent::Handler& handler) override {}
  274. void SendReadyForEntityUpdates([[maybe_unused]] bool readyForEntityUpdates) override {}
  275. AZ::TimeMs GetCurrentHostTimeMs() const override { return {}; }
  276. float GetCurrentBlendFactor() const override { return {}; }
  277. INetworkTime* GetNetworkTime() override { return {}; }
  278. INetworkEntityManager* GetNetworkEntityManager() override { return &m_manager; }
  279. void AddClientMigrationStartEventHandler([[maybe_unused]] ClientMigrationStartEvent::Handler& handler) override {}
  280. void AddClientMigrationEndEventHandler([[maybe_unused]] ClientMigrationEndEvent::Handler& handler) override {}
  281. void AddNotifyClientMigrationHandler([[maybe_unused]] NotifyClientMigrationEvent::Handler& handler) override {}
  282. void AddNotifyEntityMigrationEventHandler([[maybe_unused]] NotifyEntityMigrationEvent::Handler& handler) override {}
  283. void SendNotifyClientMigrationEvent([[maybe_unused]] AzNetworking::ConnectionId connectionId, [[maybe_unused]] const HostId& hostId,
  284. [[maybe_unused]] uint64_t userIdentifier, [[maybe_unused]] ClientInputId lastClientInputId, [[maybe_unused]] NetEntityId netEntityId) override {}
  285. void SendNotifyEntityMigrationEvent([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle, [[maybe_unused]] const HostId& remoteHostId) override {}
  286. void RegisterPlayerIdentifierForRejoin(uint64_t, NetEntityId) override {}
  287. void CompleteClientMigration(uint64_t, AzNetworking::ConnectionId, const HostId&, ClientInputId) override {}
  288. void SetShouldSpawnNetworkEntities([[maybe_unused]] bool value) override {}
  289. bool GetShouldSpawnNetworkEntities() const override { return true; }
  290. BenchmarkNetworkEntityManager& m_manager;
  291. };
  292. class HierarchyBenchmarkBase
  293. : public benchmark::Fixture
  294. , public LeakDetectionBase
  295. {
  296. public:
  297. void SetUp(const benchmark::State&) override
  298. {
  299. internalSetUp();
  300. }
  301. void SetUp(benchmark::State&) override
  302. {
  303. internalSetUp();
  304. }
  305. void TearDown(const benchmark::State&) override
  306. {
  307. internalTearDown();
  308. }
  309. void TearDown(benchmark::State&) override
  310. {
  311. internalTearDown();
  312. }
  313. virtual void internalSetUp()
  314. {
  315. AZ::NameDictionary::Create();
  316. m_ComponentApplicationRequests = AZStd::make_unique<BenchmarkComponentApplicationRequests>();
  317. AZ::Interface<AZ::ComponentApplicationRequests>::Register(m_ComponentApplicationRequests.get());
  318. // register components involved in testing
  319. m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
  320. m_transformDescriptor.reset(AzFramework::TransformComponent::CreateDescriptor());
  321. m_transformDescriptor->Reflect(m_serializeContext.get());
  322. m_netBindDescriptor.reset(NetBindComponent::CreateDescriptor());
  323. m_netBindDescriptor->Reflect(m_serializeContext.get());
  324. m_hierarchyRootDescriptor.reset(NetworkHierarchyRootComponent::CreateDescriptor());
  325. m_hierarchyRootDescriptor->Reflect(m_serializeContext.get());
  326. m_hierarchyChildDescriptor.reset(NetworkHierarchyChildComponent::CreateDescriptor());
  327. m_hierarchyChildDescriptor->Reflect(m_serializeContext.get());
  328. m_netTransformDescriptor.reset(NetworkTransformComponent::CreateDescriptor());
  329. m_netTransformDescriptor->Reflect(m_serializeContext.get());
  330. m_NetworkEntityManager = AZStd::make_unique<BenchmarkNetworkEntityManager>();
  331. m_Multiplayer = AZStd::make_unique<BenchmarkMultiplayer>(*m_NetworkEntityManager);
  332. AZ::Interface<IMultiplayer>::Register(m_Multiplayer.get());
  333. // Create space for replication stats
  334. // Without Multiplayer::RegisterMultiplayerComponents() the stats go to invalid id, which is fine for unit tests
  335. GetMultiplayer()->GetStats().ReserveComponentStats(Multiplayer::InvalidNetComponentId, 50, 0);
  336. m_Time = AZStd::make_unique<AZ::StubTimeSystem>();
  337. m_NetworkTime = AZStd::make_unique<BenchmarkNetworkTime>();
  338. AZ::Interface<INetworkTime>::Register(m_NetworkTime.get());
  339. EXPECT_NE(AZ::Interface<IMultiplayer>::Get()->GetNetworkEntityManager(), nullptr);
  340. const IpAddress address("localhost", 1, ProtocolType::Udp);
  341. m_Connection = AZStd::make_unique<BenchmarkMultiplayerConnection>(ConnectionId{ 1 }, address, ConnectionRole::Connector);
  342. m_ConnectionListener = AZStd::make_unique<BenchmarkConnectionListener>();
  343. m_entityReplicationManager = AZStd::make_unique<EntityReplicationManager>(*m_Connection, *m_ConnectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer);
  344. m_console.reset(aznew AZ::Console());
  345. AZ::Interface<AZ::IConsole>::Register(m_console.get());
  346. m_console->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead());
  347. RegisterMultiplayerComponents();
  348. }
  349. virtual void internalTearDown()
  350. {
  351. AZ::Interface<AZ::IConsole>::Unregister(m_console.get());
  352. m_console.reset();
  353. m_entityReplicationManager.reset();
  354. m_Connection.reset();
  355. m_ConnectionListener.reset();
  356. AZ::Interface<INetworkTime>::Unregister(m_NetworkTime.get());
  357. AZ::Interface<IMultiplayer>::Unregister(m_Multiplayer.get());
  358. AZ::Interface<AZ::ComponentApplicationRequests>::Unregister(m_ComponentApplicationRequests.get());
  359. m_Time.reset();
  360. m_NetworkEntityManager.reset();
  361. m_Multiplayer.reset();
  362. m_transformDescriptor.reset();
  363. m_netTransformDescriptor.reset();
  364. m_hierarchyRootDescriptor.reset();
  365. m_hierarchyChildDescriptor.reset();
  366. m_netBindDescriptor.reset();
  367. m_serializeContext.reset();
  368. m_ComponentApplicationRequests.reset();
  369. AZ::NameDictionary::Destroy();
  370. }
  371. AZStd::unique_ptr<AZ::IConsole> m_console;
  372. AZStd::unique_ptr<BenchmarkComponentApplicationRequests> m_ComponentApplicationRequests;
  373. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  374. AZStd::unique_ptr<AZ::ComponentDescriptor> m_transformDescriptor;
  375. AZStd::unique_ptr<AZ::ComponentDescriptor> m_netBindDescriptor;
  376. AZStd::unique_ptr<AZ::ComponentDescriptor> m_hierarchyRootDescriptor;
  377. AZStd::unique_ptr<AZ::ComponentDescriptor> m_hierarchyChildDescriptor;
  378. AZStd::unique_ptr<AZ::ComponentDescriptor> m_netTransformDescriptor;
  379. AZStd::unique_ptr<BenchmarkMultiplayer> m_Multiplayer;
  380. AZStd::unique_ptr<BenchmarkNetworkEntityManager> m_NetworkEntityManager;
  381. AZStd::unique_ptr<AZ::StubTimeSystem> m_Time;
  382. AZStd::unique_ptr<BenchmarkNetworkTime> m_NetworkTime;
  383. AZStd::unique_ptr<BenchmarkMultiplayerConnection> m_Connection;
  384. AZStd::unique_ptr<BenchmarkConnectionListener> m_ConnectionListener;
  385. AZStd::unique_ptr<EntityReplicationManager> m_entityReplicationManager;
  386. void SetupEntity(const AZStd::unique_ptr<AZ::Entity>& entity, NetEntityId netId, NetEntityRole role)
  387. {
  388. const auto netBindComponent = entity->FindComponent<Multiplayer::NetBindComponent>();
  389. EXPECT_NE(netBindComponent, nullptr);
  390. netBindComponent->PreInit(entity.get(), PrefabEntityId{ AZ::Name("test"), 1 }, netId, role);
  391. entity->Init();
  392. }
  393. static void StopEntity(const AZStd::unique_ptr<AZ::Entity>& entity)
  394. {
  395. const auto netBindComponent = entity->FindComponent<Multiplayer::NetBindComponent>();
  396. EXPECT_NE(netBindComponent, nullptr);
  397. netBindComponent->StopEntity();
  398. }
  399. static void StopAndDeactivateEntity(AZStd::unique_ptr<AZ::Entity>& entity)
  400. {
  401. if (entity)
  402. {
  403. StopEntity(entity);
  404. entity->Deactivate();
  405. entity.reset();
  406. }
  407. }
  408. void CreateEntityWithRootHierarchy(AZStd::unique_ptr<AZ::Entity>& rootEntity)
  409. {
  410. rootEntity->CreateComponent<AzFramework::TransformComponent>();
  411. rootEntity->CreateComponent<NetBindComponent>();
  412. rootEntity->CreateComponent<NetworkTransformComponent>();
  413. rootEntity->CreateComponent<NetworkHierarchyRootComponent>();
  414. }
  415. void CreateEntityWithChildHierarchy(AZStd::unique_ptr<AZ::Entity>& childEntity)
  416. {
  417. childEntity->CreateComponent<AzFramework::TransformComponent>();
  418. childEntity->CreateComponent<NetBindComponent>();
  419. childEntity->CreateComponent<NetworkTransformComponent>();
  420. childEntity->CreateComponent<NetworkHierarchyChildComponent>();
  421. }
  422. void SetParentIdOnNetworkTransform(const AZStd::unique_ptr<AZ::Entity>& entity, NetEntityId netParentId)
  423. {
  424. /* Derived from NetworkTransformComponent.AutoComponent.xml */
  425. constexpr int totalBits = 6 /*NetworkTransformComponentInternal::AuthorityToClientDirtyEnum::Count*/;
  426. constexpr int parentIdBit = 4 /*NetworkTransformComponentInternal::AuthorityToClientDirtyEnum::parentEntityId_DirtyFlag*/;
  427. ReplicationRecord currentRecord;
  428. currentRecord.m_authorityToClient.AddBits(totalBits);
  429. currentRecord.m_authorityToClient.SetBit(parentIdBit, true);
  430. constexpr uint32_t bufferSize = 100;
  431. AZStd::array<uint8_t, bufferSize> buffer = {};
  432. NetworkInputSerializer inSerializer(buffer.begin(), bufferSize);
  433. ISerializer& serializer = inSerializer;
  434. serializer.Serialize(netParentId, "parentEntityId"); // Derived from NetworkTransformComponent.AutoComponent.xml
  435. NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize);
  436. ReplicationRecord notifyRecord = currentRecord;
  437. entity->FindComponent<NetworkTransformComponent>()->SerializeStateDeltaMessage(currentRecord, outSerializer);
  438. entity->FindComponent<NetworkTransformComponent>()->NotifyStateDeltaChanges(notifyRecord);
  439. }
  440. template <typename Component>
  441. void SetHierarchyRootFieldOnNetworkHierarchyChild(const AZStd::unique_ptr<AZ::Entity>& entity, NetEntityId value)
  442. {
  443. /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */
  444. constexpr int totalBits = 1 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::Count*/;
  445. constexpr int inHierarchyBit = 0 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::hierarchyRoot_DirtyFlag*/;
  446. ReplicationRecord currentRecord;
  447. currentRecord.m_authorityToClient.AddBits(totalBits);
  448. currentRecord.m_authorityToClient.SetBit(inHierarchyBit, true);
  449. constexpr uint32_t bufferSize = 100;
  450. AZStd::array<uint8_t, bufferSize> buffer = {};
  451. NetworkInputSerializer inSerializer(buffer.begin(), bufferSize);
  452. ISerializer& serializer = inSerializer;
  453. serializer.Serialize(value, "hierarchyRoot"); // Derived from NetworkHierarchyChildComponent.AutoComponent.xml
  454. NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize);
  455. ReplicationRecord notifyRecord = currentRecord;
  456. entity->FindComponent<Component>()->SerializeStateDeltaMessage(currentRecord, outSerializer);
  457. entity->FindComponent<Component>()->NotifyStateDeltaChanges(notifyRecord);
  458. }
  459. struct EntityInfo
  460. {
  461. enum class Role
  462. {
  463. Root,
  464. Child,
  465. None
  466. };
  467. EntityInfo(AZ::u64 entityId, const char* entityName, NetEntityId netId, Role role)
  468. : m_entity(AZStd::make_unique<AZ::Entity>(AZ::EntityId(entityId), entityName))
  469. , m_netId(netId)
  470. , m_role(role)
  471. {
  472. }
  473. ~EntityInfo()
  474. {
  475. StopAndDeactivateEntity(m_entity);
  476. }
  477. AZStd::unique_ptr<AZ::Entity> m_entity;
  478. NetEntityId m_netId;
  479. AZStd::unique_ptr<EntityReplicator> m_replicator;
  480. Role m_role = Role::None;
  481. };
  482. void PopulateHierarchicalEntity(const EntityInfo& entityInfo)
  483. {
  484. entityInfo.m_entity->CreateComponent<AzFramework::TransformComponent>();
  485. entityInfo.m_entity->CreateComponent<NetBindComponent>();
  486. entityInfo.m_entity->CreateComponent<NetworkTransformComponent>();
  487. switch (entityInfo.m_role)
  488. {
  489. case EntityInfo::Role::Root:
  490. entityInfo.m_entity->CreateComponent<NetworkHierarchyRootComponent>();
  491. break;
  492. case EntityInfo::Role::Child:
  493. entityInfo.m_entity->CreateComponent<NetworkHierarchyChildComponent>();
  494. break;
  495. case EntityInfo::Role::None:
  496. break;
  497. }
  498. }
  499. void CreateParent(EntityInfo& parent)
  500. {
  501. PopulateHierarchicalEntity(parent);
  502. SetupEntity(parent.m_entity, parent.m_netId, NetEntityRole::Authority);
  503. // Create an entity replicator for the child entity
  504. const NetworkEntityHandle childHandle(parent.m_entity.get(), m_NetworkEntityManager->GetNetworkEntityTracker());
  505. parent.m_replicator = AZStd::make_unique<EntityReplicator>(*m_entityReplicationManager, m_Connection.get(), NetEntityRole::Client, childHandle);
  506. parent.m_replicator->Initialize(childHandle);
  507. parent.m_entity->Activate();
  508. }
  509. void CreateChildForParent(EntityInfo& child, EntityInfo& parent)
  510. {
  511. PopulateHierarchicalEntity(child);
  512. SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority);
  513. // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller)
  514. SetParentIdOnNetworkTransform(child.m_entity, parent.m_netId);
  515. // Create an entity replicator for the child entity
  516. const NetworkEntityHandle childHandle(child.m_entity.get(), m_NetworkEntityManager->GetNetworkEntityTracker());
  517. child.m_replicator = AZStd::make_unique<EntityReplicator>(*m_entityReplicationManager, m_Connection.get(), NetEntityRole::Client, childHandle);
  518. child.m_replicator->Initialize(childHandle);
  519. child.m_entity->Activate();
  520. }
  521. void ForceRebuildHierarchy(const AZStd::unique_ptr<AZ::Entity>& rootEntity)
  522. {
  523. if (NetworkHierarchyRootComponent* root = rootEntity->FindComponent<NetworkHierarchyRootComponent>())
  524. {
  525. root->RebuildHierarchy();
  526. }
  527. }
  528. };
  529. }
  530. #endif