ServerToClientConnectionData.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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/ConnectionData/ServerToClientConnectionData.h>
  9. #include <Source/AutoGen/Multiplayer.AutoPackets.h>
  10. #include <Multiplayer/Components/LocalPredictionPlayerInputComponent.h>
  11. #include <Multiplayer/IMultiplayer.h>
  12. #include <AzNetworking/Utilities/EncryptionCommon.h>
  13. namespace Multiplayer
  14. {
  15. // This can be used to help mitigate client side performance when large numbers of entities are created off the network
  16. AZ_CVAR(uint32_t, sv_ClientMaxRemoteEntitiesPendingCreationCount, AZStd::numeric_limits<uint32_t>::max(), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Maximum number of entities that we have sent to the client, but have not had a confirmation back from the client");
  17. AZ_CVAR(uint32_t, sv_ClientMaxRemoteEntitiesPendingCreationCountPostInit, AZStd::numeric_limits<uint32_t>::max(), nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Maximum number of entities that we will send to clients after gameplay has begun");
  18. AZ_CVAR(AZ::TimeMs, sv_ClientEntityReplicatorPendingRemovalTimeMs, AZ::TimeMs{ 10000 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "How long should wait prior to removing an entity for the client through a change in the replication window, entity deletes are still immediate");
  19. ServerToClientConnectionData::ServerToClientConnectionData
  20. (
  21. AzNetworking::IConnection* connection,
  22. AzNetworking::IConnectionListener& connectionListener
  23. )
  24. : m_connection(connection)
  25. , m_controlledEntityRemovedHandler([this](const ConstNetworkEntityHandle&) { OnControlledEntityRemove(); })
  26. , m_controlledEntityMigrationHandler([this](const ConstNetworkEntityHandle& entityHandle, const HostId& remoteHostId)
  27. {
  28. OnControlledEntityMigration(entityHandle, remoteHostId);
  29. })
  30. , m_entityReplicationManager(*connection, connectionListener, EntityReplicationManager::Mode::LocalServerToRemoteClient)
  31. {
  32. m_entityReplicationManager.SetMaxRemoteEntitiesPendingCreationCount(sv_ClientMaxRemoteEntitiesPendingCreationCount);
  33. m_entityReplicationManager.SetEntityPendingRemovalMs(sv_ClientEntityReplicatorPendingRemovalTimeMs);
  34. }
  35. ServerToClientConnectionData::~ServerToClientConnectionData()
  36. {
  37. m_entityReplicationManager.Clear(false);
  38. m_controlledEntityRemovedHandler.Disconnect();
  39. }
  40. void ServerToClientConnectionData::SetControlledEntity(NetworkEntityHandle primaryPlayerEntity)
  41. {
  42. m_controlledEntityRemovedHandler.Disconnect();
  43. m_controlledEntityMigrationHandler.Disconnect();
  44. m_controlledEntity = primaryPlayerEntity;
  45. NetBindComponent* netBindComponent = m_controlledEntity.GetNetBindComponent();
  46. if (netBindComponent != nullptr)
  47. {
  48. netBindComponent->AddEntityStopEventHandler(m_controlledEntityRemovedHandler);
  49. netBindComponent->AddEntityServerMigrationEventHandler(m_controlledEntityMigrationHandler);
  50. }
  51. }
  52. ConnectionDataType ServerToClientConnectionData::GetConnectionDataType() const
  53. {
  54. return ConnectionDataType::ServerToClient;
  55. }
  56. AzNetworking::IConnection* ServerToClientConnectionData::GetConnection() const
  57. {
  58. return m_connection;
  59. }
  60. EntityReplicationManager& ServerToClientConnectionData::GetReplicationManager()
  61. {
  62. return m_entityReplicationManager;
  63. }
  64. void ServerToClientConnectionData::Update()
  65. {
  66. m_entityReplicationManager.ActivatePendingEntities();
  67. if (CanSendUpdates())
  68. {
  69. NetBindComponent* netBindComponent = m_controlledEntity.GetNetBindComponent();
  70. // potentially false if we just migrated the player, if that is the case, don't send any more updates
  71. if (netBindComponent != nullptr && (netBindComponent->GetNetEntityRole() == NetEntityRole::Authority))
  72. {
  73. m_entityReplicationManager.SendUpdates();
  74. }
  75. }
  76. }
  77. void ServerToClientConnectionData::OnControlledEntityRemove()
  78. {
  79. m_connection->Disconnect(AzNetworking::DisconnectReason::TerminatedByServer, AzNetworking::TerminationEndpoint::Local);
  80. m_entityReplicationManager.Clear(false);
  81. m_controlledEntity.Reset();
  82. }
  83. void ServerToClientConnectionData::OnControlledEntityMigration
  84. (
  85. [[maybe_unused]] const ConstNetworkEntityHandle& entityHandle,
  86. const HostId& remoteHostId
  87. )
  88. {
  89. ClientInputId migratedClientInputId = ClientInputId{ 0 };
  90. if (m_controlledEntity != nullptr)
  91. {
  92. auto controller = m_controlledEntity.FindController<LocalPredictionPlayerInputComponentController>();
  93. if (controller != nullptr)
  94. {
  95. migratedClientInputId = controller->GetLastInputId();
  96. }
  97. }
  98. // Generate crypto-rand user identifier, send to both server and client so they can negotiate the autonomous entity to assume predictive control over after migration
  99. const uint64_t temporaryUserIdentifier = AzNetworking::CryptoRand64();
  100. // Tell the new host that a client is about to (re)join
  101. GetMultiplayer()->SendNotifyClientMigrationEvent(GetConnection()->GetConnectionId(), remoteHostId, temporaryUserIdentifier, migratedClientInputId, m_controlledEntity.GetNetEntityId());
  102. // We need to send a MultiplayerPackets::ClientMigration packet to complete this process
  103. // This happens inside MultiplayerSystemComponent, once we're certain the remote host has appropriately prepared
  104. m_controlledEntity = NetworkEntityHandle();
  105. m_canSendUpdates = false;
  106. }
  107. void ServerToClientConnectionData::OnGameplayStarted()
  108. {
  109. m_entityReplicationManager.SetMaxRemoteEntitiesPendingCreationCount(sv_ClientMaxRemoteEntitiesPendingCreationCountPostInit);
  110. }
  111. }