MultiplayerSystemComponent.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. #include <Multiplayer/IMultiplayer.h>
  10. #include <Multiplayer/Session/ISessionHandlingRequests.h>
  11. #include <Multiplayer/Session/SessionNotifications.h>
  12. #include <Editor/MultiplayerEditorConnection.h>
  13. #include <NetworkTime/NetworkTime.h>
  14. #include <NetworkEntity/NetworkEntityManager.h>
  15. #include <Source/AutoGen/Multiplayer.AutoPacketDispatcher.h>
  16. #include <AzCore/Component/Component.h>
  17. #include <AzCore/Component/TickBus.h>
  18. #include <AzCore/Console/IConsole.h>
  19. #include <AzCore/Threading/ThreadSafeDeque.h>
  20. #include <AzCore/std/string/string.h>
  21. #include <AzFramework/API/ApplicationAPI.h>
  22. #include <AzFramework/Physics/Common/PhysicsEvents.h>
  23. #include <AzNetworking/ConnectionLayer/IConnectionListener.h>
  24. // This can be overridden in the build files by defining O3DE_EDITOR_CONNECTION_LISTENER_ENABLE to 0 or 1
  25. // to force disabling or enabling the listener. But by default, it will be enabled in non-monolithic builds
  26. // and disabled in monolithic builds.
  27. #if !defined(O3DE_EDITOR_CONNECTION_LISTENER_ENABLE)
  28. #if !defined(AZ_MONOLITHIC_BUILD)
  29. #define O3DE_EDITOR_CONNECTION_LISTENER_ENABLE 1
  30. #endif
  31. #endif
  32. namespace AzFramework
  33. {
  34. struct SessionConfig;
  35. }
  36. namespace AzNetworking
  37. {
  38. class INetworkInterface;
  39. }
  40. namespace Multiplayer
  41. {
  42. //! Multiplayer system component wraps the bridging logic between the game and transport layer.
  43. class MultiplayerSystemComponent final
  44. : public AZ::Component
  45. , public AZ::TickBus::Handler
  46. , public SessionNotificationBus::Handler
  47. , public ISessionHandlingClientRequests
  48. , public AzNetworking::IConnectionListener
  49. , public IMultiplayer
  50. , AzFramework::RootSpawnableNotificationBus::Handler
  51. , AzFramework::LevelLoadBlockerBus::Handler
  52. {
  53. public:
  54. AZ_COMPONENT(MultiplayerSystemComponent, "{7C99C4C1-1103-43F9-AD62-8B91CF7C1981}");
  55. static void Reflect(AZ::ReflectContext* context);
  56. static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
  57. static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
  58. static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
  59. MultiplayerSystemComponent();
  60. ~MultiplayerSystemComponent() override;
  61. //! AZ::Component overrides.
  62. //! @{
  63. void Activate() override;
  64. void Deactivate() override;
  65. //! @}
  66. //! SessionNotificationBus::Handler overrides.
  67. //! @{
  68. bool OnSessionHealthCheck() override;
  69. bool OnCreateSessionBegin(const SessionConfig& sessionConfig) override;
  70. void OnCreateSessionEnd() override;
  71. bool OnDestroySessionBegin() override;
  72. void OnDestroySessionEnd() override;
  73. void OnUpdateSessionBegin(const SessionConfig& sessionConfig, const AZStd::string& updateReason) override;
  74. void OnUpdateSessionEnd() override;
  75. //! @}
  76. //! AZ::TickBus::Handler overrides.
  77. //! @{
  78. void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
  79. int GetTickOrder() override;
  80. //! @}
  81. bool IsHandshakeComplete(AzNetworking::IConnection* connection) const;
  82. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::Connect& packet);
  83. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::Accept& packet);
  84. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ReadyForEntityUpdates& packet);
  85. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::SyncConsole& packet);
  86. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ConsoleCommand& packet);
  87. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::EntityUpdates& packet);
  88. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::EntityRpcs& packet);
  89. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::RequestReplicatorReset& packet);
  90. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::ClientMigration& packet);
  91. bool HandleRequest(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, MultiplayerPackets::VersionMismatch& packet);
  92. //! IConnectionListener interface
  93. //! @{
  94. AzNetworking::ConnectResult ValidateConnect(const AzNetworking::IpAddress& remoteAddress, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer) override;
  95. void OnConnect(AzNetworking::IConnection* connection) override;
  96. AzNetworking::PacketDispatchResult OnPacketReceived(AzNetworking::IConnection* connection, const AzNetworking::IPacketHeader& packetHeader, AzNetworking::ISerializer& serializer) override;
  97. void OnPacketLost(AzNetworking::IConnection* connection, AzNetworking::PacketId packetId) override;
  98. void OnDisconnect(AzNetworking::IConnection* connection, AzNetworking::DisconnectReason reason, AzNetworking::TerminationEndpoint endpoint) override;
  99. //! @}
  100. //! ISessionHandlingClientRequests interface
  101. //! @{
  102. bool RequestPlayerJoinSession(const SessionConnectionConfig& sessionConnectionConfig) override;
  103. void RequestPlayerLeaveSession() override;
  104. //! @}
  105. //! IMultiplayer interface
  106. //! @{
  107. MultiplayerAgentType GetAgentType() const override;
  108. void InitializeMultiplayer(MultiplayerAgentType state) override;
  109. bool StartHosting(uint16_t port = UseDefaultHostPort, bool isDedicated = true) override;
  110. bool Connect(const AZStd::string& remoteAddress, uint16_t port, const AZStd::string& connectionTicket = "") override;
  111. void Terminate(AzNetworking::DisconnectReason reason) override;
  112. void AddClientMigrationStartEventHandler(ClientMigrationStartEvent::Handler& handler) override;
  113. void AddClientMigrationEndEventHandler(ClientMigrationEndEvent::Handler& handler) override;
  114. void AddEndpointDisconnectedHandler(EndpointDisconnectedEvent::Handler& handler) override;
  115. void AddNotifyClientMigrationHandler(NotifyClientMigrationEvent::Handler& handler) override;
  116. void AddNotifyEntityMigrationEventHandler(NotifyEntityMigrationEvent::Handler& handler) override;
  117. void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) override;
  118. void AddNetworkInitHandler(NetworkInitEvent::Handler& handler) override;
  119. //! @deprecated If looking for an event when a multiplayer session is created, use SessionNotificationBus::OnCreateSessionBegin or
  120. //! SessionNotificationBus::OnCreateSessionEnd.
  121. void AddSessionInitHandler(SessionInitEvent::Handler&) override {}
  122. //! @deprecated If looking for an event when the multiplayer session ends, use SessionNotificationBus::OnDestroySessionBegin or
  123. //! SessionNotificationBus::OnDestroySessionEnd.
  124. void AddSessionShutdownHandler(SessionShutdownEvent::Handler&) override {}
  125. void AddLevelLoadBlockedHandler(LevelLoadBlockedEvent::Handler& handler) override;
  126. void AddNoServerLevelLoadedHandler(NoServerLevelLoadedEvent::Handler& handler) override;
  127. void AddVersionMismatchHandler(VersionMismatchEvent::Handler& handler) override;
  128. void AddServerAcceptanceReceivedHandler(ServerAcceptanceReceivedEvent::Handler& handler) override;
  129. void SendNotifyClientMigrationEvent(AzNetworking::ConnectionId connectionId, const HostId& hostId, uint64_t userIdentifier, ClientInputId lastClientInputId, NetEntityId controlledEntityId) override;
  130. void SendNotifyEntityMigrationEvent(const ConstNetworkEntityHandle& entityHandle, const HostId& remoteHostId) override;
  131. void SendReadyForEntityUpdates(bool readyForEntityUpdates) override;
  132. AZ::TimeMs GetCurrentHostTimeMs() const override;
  133. float GetCurrentBlendFactor() const override;
  134. INetworkTime* GetNetworkTime() override;
  135. INetworkEntityManager* GetNetworkEntityManager() override;
  136. void RegisterPlayerIdentifierForRejoin(uint64_t temporaryUserIdentifier, NetEntityId controlledEntityId) override;
  137. void CompleteClientMigration(uint64_t temporaryUserIdentifier, AzNetworking::ConnectionId connectionId, const HostId& publicHostId, ClientInputId migratedClientInputId) override;
  138. void SetShouldSpawnNetworkEntities(bool value) override;
  139. bool GetShouldSpawnNetworkEntities() const override;
  140. //! @}
  141. //! Console commands.
  142. //! @{
  143. void DumpStats(const AZ::ConsoleCommandContainer& arguments);
  144. //! @}
  145. //! AzFramework::RootSpawnableNotificationBus::Handler
  146. //! @{
  147. void OnRootSpawnableAssigned(AZ::Data::Asset<AzFramework::Spawnable> rootSpawnable, uint32_t generation) override;
  148. void OnRootSpawnableReady(AZ::Data::Asset<AzFramework::Spawnable> rootSpawnable, uint32_t generation) override;
  149. void OnRootSpawnableReleased(uint32_t generation) override;
  150. //! @}
  151. //! AzFramework::LevelLoadBlockerBus::Handler overrides.
  152. //! @{
  153. bool ShouldBlockLevelLoading(const char* levelName) override;
  154. //! @}
  155. private:
  156. bool IsHosting() const;
  157. bool AttemptPlayerConnect(AzNetworking::IConnection* connection, MultiplayerPackets::Connect& packet);
  158. void TickVisibleNetworkEntities(float deltaTime, float serverRateSeconds);
  159. void OnConsoleCommandInvoked(AZStd::string_view command, const AZ::ConsoleCommandContainer& args, AZ::ConsoleFunctorFlags flags, AZ::ConsoleInvokedFrom invokedFrom);
  160. void OnAutonomousEntityReplicatorCreated();
  161. void ExecuteConsoleCommandList(AzNetworking::IConnection* connection, const AZStd::fixed_vector<Multiplayer::LongNetworkString, 32>& commands);
  162. static void EnableAutonomousControl(NetworkEntityHandle entityHandle, AzNetworking::ConnectionId ownerConnectionId);
  163. static void StartServerToClientReplication(uint64_t userId, NetworkEntityHandle controlledEntity, AzNetworking::IConnection* connection);
  164. AZ_CONSOLEFUNC(MultiplayerSystemComponent, DumpStats, AZ::ConsoleFunctorFlags::Null, "Dumps stats for the current multiplayer session");
  165. void HostConsoleCommand(const AZ::ConsoleCommandContainer& arguments);
  166. void ConnectConsoleCommand(const AZ::ConsoleCommandContainer& arguments);
  167. AZStd::unique_ptr<AZ::ConsoleFunctor<MultiplayerSystemComponent, false>> m_hostConsoleCommand;
  168. AZStd::unique_ptr<AZ::ConsoleFunctor<MultiplayerSystemComponent, false>> m_connectConsoleCommand;
  169. AzNetworking::INetworkInterface* m_networkInterface = nullptr;
  170. AZ::ConsoleCommandInvokedEvent::Handler m_consoleCommandHandler;
  171. AZ::ThreadSafeDeque<AZStd::string> m_cvarCommands;
  172. NetworkEntityManager m_networkEntityManager;
  173. NetworkTime m_networkTime;
  174. MultiplayerAgentType m_agentType = MultiplayerAgentType::Uninitialized;
  175. IFilterEntityManager* m_filterEntityManager = nullptr; // non-owning pointer
  176. ConnectionAcquiredEvent m_connectionAcquiredEvent;
  177. NetworkInitEvent m_networkInitEvent;
  178. ServerAcceptanceReceivedEvent m_serverAcceptanceReceivedEvent;
  179. EndpointDisconnectedEvent m_endpointDisconnectedEvent;
  180. ClientMigrationStartEvent m_clientMigrationStartEvent;
  181. ClientMigrationEndEvent m_clientMigrationEndEvent;
  182. NotifyClientMigrationEvent m_notifyClientMigrationEvent;
  183. NotifyEntityMigrationEvent m_notifyEntityMigrationEvent;
  184. LevelLoadBlockedEvent m_levelLoadBlockedEvent;
  185. NoServerLevelLoadedEvent m_noServerLevelLoadedEvent;
  186. VersionMismatchEvent m_versionMismatchEvent;
  187. AZ::Event<NetEntityId>::Handler m_autonomousEntityReplicatorCreatedHandler;
  188. AZ::SettingsRegistryInterface::NotifyEventHandler m_componentApplicationLifecycleHandler;
  189. AZStd::queue<AZStd::string> m_pendingConnectionTickets;
  190. AZStd::unordered_map<uint64_t, NetEntityId> m_playerRejoinData;
  191. AZ::TimeMs m_lastReplicatedHostTimeMs = AZ::Time::ZeroTimeMs;
  192. HostFrameId m_lastReplicatedHostFrameId = HostFrameId{0};
  193. uint64_t m_temporaryUserIdentifier = 0; // Used in the event of a migration or rejoin
  194. double m_serverSendAccumulator = 0.0;
  195. float m_renderBlendFactor = 0.0f;
  196. float m_tickFactor = 0.0f;
  197. bool m_spawnNetboundEntities = false;
  198. // Store player information if they connect before there is a level and IPlayerSpawner available
  199. struct PlayerWaitingToBeSpawned
  200. {
  201. PlayerWaitingToBeSpawned(uint64_t userId, MultiplayerAgentDatum agent, AzNetworking::IConnection* connection)
  202. : userId(userId), agent(agent), connection(connection)
  203. {
  204. }
  205. uint64_t userId;
  206. MultiplayerAgentDatum agent;
  207. AzNetworking::IConnection* connection = nullptr;
  208. };
  209. AZStd::vector<PlayerWaitingToBeSpawned> m_playersWaitingToBeSpawned;
  210. bool m_blockClientLoadLevel = true;
  211. bool m_levelEntitiesActivated = false;
  212. AZStd::unordered_map<AzNetworking::ConnectionId, MultiplayerPackets::Connect> m_originalConnectPackets;
  213. void RegisterMetrics();
  214. void MetricsEvent();
  215. AZ::ScheduledEvent m_metricsEvent{ [this]()
  216. {
  217. MetricsEvent();
  218. }, AZ::Name("MultiplayerSystemComponent Metrics") };
  219. void UpdatedMetricsConnectionCount();
  220. void UpdateConnections();
  221. void OnPhysicsPreSimulate(float dt);
  222. AzPhysics::SystemEvents::OnPresimulateEvent::Handler m_preSimulateHandler{[this](float dt)
  223. {
  224. OnPhysicsPreSimulate(dt);
  225. }};
  226. AZStd::chrono::steady_clock::time_point m_startPhysicsTickTime;
  227. void OnPhysicsPostSimulate(float dt);
  228. AzPhysics::SystemEvents::OnPostsimulateEvent::Handler m_postSimulateHandler{ [this](float dt)
  229. {
  230. OnPhysicsPostSimulate(dt);
  231. } };
  232. // By default, this is only enabled in non-monolithic builds, since the Editor doesn't support monolithic builds.
  233. #if (O3DE_EDITOR_CONNECTION_LISTENER_ENABLE)
  234. // This is a unique_ptr instead of a raw instance so that we can defer the construction
  235. // until the Activate(). If it gets constructed during the MultiplayerSystemComponent constructor,
  236. // the AzNetworking systems might not be constructed and activated yet, which would crash.
  237. AZStd::unique_ptr<MultiplayerEditorConnection> m_editorConnectionListener;
  238. #endif
  239. };
  240. }