Cleanup session changes and add on connection disconnected event

This commit is contained in:
puvvadar
2021-06-08 16:43:36 -07:00
parent fa55b495c4
commit cd5867d2fa
8 changed files with 76 additions and 25 deletions
@@ -45,6 +45,7 @@ namespace Multiplayer
AzNetworking::ByteBuffer<2048> m_userData; AzNetworking::ByteBuffer<2048> m_userData;
}; };
using ClientDisconnectedEvent = AZ::Event<>;
using ConnectionAcquiredEvent = AZ::Event<MultiplayerAgentDatum>; using ConnectionAcquiredEvent = AZ::Event<MultiplayerAgentDatum>;
using SessionInitEvent = AZ::Event<AzNetworking::INetworkInterface*>; using SessionInitEvent = AZ::Event<AzNetworking::INetworkInterface*>;
using SessionShutdownEvent = AZ::Event<AzNetworking::INetworkInterface*>; using SessionShutdownEvent = AZ::Event<AzNetworking::INetworkInterface*>;
@@ -65,8 +66,12 @@ namespace Multiplayer
//! @param state The state of this connection //! @param state The state of this connection
virtual void InitializeMultiplayer(MultiplayerAgentType state) = 0; virtual void InitializeMultiplayer(MultiplayerAgentType state) = 0;
//! Adds a ClientDisconnectedEvent Handler which is invoked on the client when a disconnectio occurs
//! @param handler The ClientDisconnectedEvent Handler to add
virtual void AddClientDisconnectedHandler(ClientDisconnectedEvent::Handler& handler) = 0;
//! Adds a ConnectionAcquiredEvent Handler which is invoked when a new endpoint connects to the session. //! Adds a ConnectionAcquiredEvent Handler which is invoked when a new endpoint connects to the session.
//! @param handler The SessionInitEvent Handler to add //! @param handler The ConnectionAcquiredEvent Handler to add
virtual void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) = 0; virtual void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) = 0;
//! Adds a SessionInitEvent Handler which is invoked when a new network session starts. //! Adds a SessionInitEvent Handler which is invoked when a new network session starts.
@@ -22,7 +22,7 @@ namespace Multiplayer
( (
AzNetworking::IConnection* connection, AzNetworking::IConnection* connection,
AzNetworking::IConnectionListener& connectionListener, AzNetworking::IConnectionListener& connectionListener,
AZStd::string providerTicket const AZStd::string& providerTicket
) )
: m_connection(connection) : m_connection(connection)
, m_entityReplicationManager(*connection, connectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer) , m_entityReplicationManager(*connection, connectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer)
@@ -25,7 +25,7 @@ namespace Multiplayer
( (
AzNetworking::IConnection* connection, AzNetworking::IConnection* connection,
AzNetworking::IConnectionListener& connectionListener, AzNetworking::IConnectionListener& connectionListener,
AZStd::string providerTicket = "" const AZStd::string& providerTicket = ""
); );
~ClientToServerConnectionData() override; ~ClientToServerConnectionData() override;
@@ -39,7 +39,7 @@ namespace Multiplayer
void SetCanSendUpdates(bool canSendUpdates) override; void SetCanSendUpdates(bool canSendUpdates) override;
//! @} //! @}
AZStd::string GetProviderTicket() const; const AZStd::string& GetProviderTicket() const;
private: private:
EntityReplicationManager m_entityReplicationManager; EntityReplicationManager m_entityReplicationManager;
@@ -22,7 +22,7 @@ namespace Multiplayer
m_canSendUpdates = canSendUpdates; m_canSendUpdates = canSendUpdates;
} }
inline AZStd::string ClientToServerConnectionData::GetProviderTicket() const inline const AZStd::string& ClientToServerConnectionData::GetProviderTicket() const
{ {
return m_providerTicket; return m_providerTicket;
} }
@@ -41,7 +41,7 @@ namespace Multiplayer
NetworkEntityHandle GetPrimaryPlayerEntity(); NetworkEntityHandle GetPrimaryPlayerEntity();
const NetworkEntityHandle& GetPrimaryPlayerEntity() const; const NetworkEntityHandle& GetPrimaryPlayerEntity() const;
AZStd::string GetProviderTicket() const; const AZStd::string& GetProviderTicket() const;
void SetProviderTicket(AZStd::string); void SetProviderTicket(AZStd::string);
private: private:
@@ -33,7 +33,7 @@ namespace Multiplayer
return m_controlledEntity; return m_controlledEntity;
} }
inline AZStd::string ServerToClientConnectionData::GetProviderTicket() const inline const AZStd::string& ServerToClientConnectionData::GetProviderTicket() const
{ {
return m_ticket; return m_ticket;
} }
@@ -117,6 +117,31 @@ namespace Multiplayer
behaviorContext->Class<RpcIndex>(); behaviorContext->Class<RpcIndex>();
behaviorContext->Class<ClientInputId>(); behaviorContext->Class<ClientInputId>();
behaviorContext->Class<HostFrameId>(); behaviorContext->Class<HostFrameId>();
behaviorContext->Class<MultiplayerSystemComponent>("MultiplayerSystemComponent")
->Attribute(AZ::Script::Attributes::Module, "multiplayer")
->Attribute(AZ::Script::Attributes::Category, "Multiplayer")
->Method("GetOnClientDisconnectedEvent", [](AZ::EntityId id) -> AZ::Event<>*
{
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(id);
if (!entity)
{
AZ_Warning("Network Property", false, "NetworkTransformComponent GetOnScaleChangedEvent failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
return nullptr;
}
MultiplayerSystemComponent* mpComponent = entity->FindComponent<MultiplayerSystemComponent>();
if (!mpComponent)
{
AZ_Warning("Multiplayer Property", false, "NetworkTransformComponent GetScale failed. Entity '%s' (id: %s) is missing NetworkTransformComponent, be sure to add NetworkTransformComponent to this entity.", entity->GetName().c_str(), id.ToString().c_str())
return nullptr;
}
return &mpComponent->m_clientDisconnectedEvent;
})
->Attribute(
AZ::Script::Attributes::AzEventDescription,
AZ::BehaviorAzEventDescription{"On Client Disconnected Event"});
} }
MultiplayerComponent::Reflect(context); MultiplayerComponent::Reflect(context);
@@ -173,12 +198,11 @@ namespace Multiplayer
bool MultiplayerSystemComponent::RequestPlayerJoinSession(const AzFramework::SessionConnectionConfig& config) bool MultiplayerSystemComponent::RequestPlayerJoinSession(const AzFramework::SessionConnectionConfig& config)
{ {
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client); AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Client);
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MPNetworkInterfaceName));
const IpAddress ipAddress(config.m_ipAddress.c_str(), config.m_port, networkInterface->GetType()); const IpAddress ipAddress(config.m_ipAddress.c_str(), config.m_port, m_networkInterface->GetType());
ConnectionId connectionId = networkInterface->Connect(ipAddress); ConnectionId connectionId = m_networkInterface->Connect(ipAddress);
AzNetworking::IConnection* connection = networkInterface->GetConnectionSet().GetConnection(connectionId); AzNetworking::IConnection* connection = m_networkInterface->GetConnectionSet().GetConnection(connectionId);
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
{ {
connection->SetUserData(new ClientToServerConnectionData(connection, *this, config.m_playerSessionId)); connection->SetUserData(new ClientToServerConnectionData(connection, *this, config.m_playerSessionId));
@@ -188,10 +212,15 @@ namespace Multiplayer
void MultiplayerSystemComponent::RequestPlayerLeaveSession() void MultiplayerSystemComponent::RequestPlayerLeaveSession()
{ {
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Uninitialized); if (GetAgentType() == MultiplayerAgentType::Client)
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(MPNetworkInterfaceName)); {
auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); }; AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(MultiplayerAgentType::Uninitialized);
networkInterface->GetConnectionSet().VisitConnections(visitor); auto visitor = [](IConnection& connection)
{
connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local);
};
m_networkInterface->GetConnectionSet().VisitConnections(visitor);
}
} }
bool MultiplayerSystemComponent::OnSessionHealthCheck() bool MultiplayerSystemComponent::OnSessionHealthCheck()
@@ -379,19 +408,24 @@ namespace Multiplayer
[[maybe_unused]] MultiplayerPackets::Connect& packet [[maybe_unused]] MultiplayerPackets::Connect& packet
) )
{ {
if (connection->SendReliablePacket(MultiplayerPackets::Accept(InvalidHostId, sv_map))) // Validate our session with the provider if any
if (AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get() != nullptr)
{ {
// Validate our session with the provider if any AzFramework::PlayerConnectionConfig config;
if (AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get() != nullptr) config.m_playerConnectionId = aznumeric_cast<uint32_t>(connection->GetConnectionId());
config.m_playerSessionId = packet.GetTicket();
if(!AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get()->ValidatePlayerJoinSession(config))
{ {
AzFramework::PlayerConnectionConfig config; auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); };
config.m_playerConnectionId = aznumeric_cast<uint32_t>(connection->GetConnectionId()); m_networkInterface->GetConnectionSet().VisitConnections(visitor);
config.m_playerSessionId = packet.GetTicket(); return true;
AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get()->ValidatePlayerJoinSession(config);
reinterpret_cast<ServerToClientConnectionData*>(connection->GetUserData())->SetProviderTicket(packet.GetTicket().c_str());
} }
reinterpret_cast<ServerToClientConnectionData*>(connection->GetUserData())->SetProviderTicket(packet.GetTicket().c_str());
}
if (connection->SendReliablePacket(MultiplayerPackets::Accept(InvalidHostId, sv_map)))
{
// Sync our console // Sync our console
ConsoleReplicator consoleReplicator(connection); ConsoleReplicator consoleReplicator(connection);
AZ::Interface<AZ::IConsole>::Get()->VisitRegisteredFunctors([&consoleReplicator](AZ::ConsoleFunctorBase* functor) { consoleReplicator.Visit(functor); }); AZ::Interface<AZ::IConsole>::Get()->VisitRegisteredFunctors([&consoleReplicator](AZ::ConsoleFunctorBase* functor) { consoleReplicator.Visit(functor); });
@@ -606,11 +640,16 @@ namespace Multiplayer
AZStd::string reasonString = ToString(reason); AZStd::string reasonString = ToString(reason);
AZLOG_INFO("%s due to %s from remote address: %s", endpointString, reasonString.c_str(), connection->GetRemoteAddress().GetString().c_str()); AZLOG_INFO("%s due to %s from remote address: %s", endpointString, reasonString.c_str(), connection->GetRemoteAddress().GetString().c_str());
// The authority is shutting down its connection
if (connection->GetConnectionRole() == ConnectionRole::Acceptor) if (connection->GetConnectionRole() == ConnectionRole::Acceptor)
{ {
// The authority is shutting down its connection
m_shutdownEvent.Signal(m_networkInterface); m_shutdownEvent.Signal(m_networkInterface);
} }
else if (GetAgentType() == MultiplayerAgentType::Client && connection->GetConnectionRole() == ConnectionRole::Connector)
{
// The client is disconnecting
m_clientDisconnectedEvent.Signal();
}
// Clean up any multiplayer connection data we've bound to this connection instance // Clean up any multiplayer connection data we've bound to this connection instance
if (connection->GetUserData() != nullptr) if (connection->GetUserData() != nullptr)
@@ -679,6 +718,11 @@ namespace Multiplayer
AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType)); AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType));
} }
void MultiplayerSystemComponent::AddClientDisconnectedHandler(ClientDisconnectedEvent::Handler& handler)
{
handler.Connect(m_clientDisconnectedEvent);
}
void MultiplayerSystemComponent::AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) void MultiplayerSystemComponent::AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler)
{ {
handler.Connect(m_connAcquiredEvent); handler.Connect(m_connAcquiredEvent);
@@ -108,6 +108,7 @@ namespace Multiplayer
//! @{ //! @{
MultiplayerAgentType GetAgentType() const override; MultiplayerAgentType GetAgentType() const override;
void InitializeMultiplayer(MultiplayerAgentType state) override; void InitializeMultiplayer(MultiplayerAgentType state) override;
void AddClientDisconnectedHandler(ClientDisconnectedEvent::Handler& handler) override;
void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) override; void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) override;
void AddSessionInitHandler(SessionInitEvent::Handler& handler) override; void AddSessionInitHandler(SessionInitEvent::Handler& handler) override;
void AddSessionShutdownHandler(SessionShutdownEvent::Handler& handler) override; void AddSessionShutdownHandler(SessionShutdownEvent::Handler& handler) override;
@@ -143,6 +144,7 @@ namespace Multiplayer
SessionInitEvent m_initEvent; SessionInitEvent m_initEvent;
SessionShutdownEvent m_shutdownEvent; SessionShutdownEvent m_shutdownEvent;
ConnectionAcquiredEvent m_connAcquiredEvent; ConnectionAcquiredEvent m_connAcquiredEvent;
ClientDisconnectedEvent m_clientDisconnectedEvent;
AZ::TimeMs m_lastReplicatedHostTimeMs = AZ::TimeMs{ 0 }; AZ::TimeMs m_lastReplicatedHostTimeMs = AZ::TimeMs{ 0 };
HostFrameId m_lastReplicatedHostFrameId = InvalidHostFrameId; HostFrameId m_lastReplicatedHostFrameId = InvalidHostFrameId;