Cleanup session changes and add on connection disconnected event
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user