Changes to make client and entity migration functional, needed in the event of a host quitting necessitating a host migration
Signed-off-by: kberg-amzn <karlberg@amazon.com>
This commit is contained in:
@@ -123,8 +123,8 @@ namespace Multiplayer
|
||||
if (IsAutonomous())
|
||||
{
|
||||
m_autonomousUpdateEvent.Enqueue(AZ::TimeMs{ 1 }, true);
|
||||
GetParent().GetNetBindComponent()->AddEntityMigrationStartEventHandler(m_migrateStartHandler);
|
||||
GetParent().GetNetBindComponent()->AddEntityMigrationEndEventHandler(m_migrateEndHandler);
|
||||
GetMultiplayer()->AddClientMigrationStartEventHandler(m_migrateStartHandler);
|
||||
GetMultiplayer()->AddClientMigrationEndEventHandler(m_migrateEndHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -388,16 +388,6 @@ namespace Multiplayer
|
||||
m_syncRewindEvent.Signal();
|
||||
}
|
||||
|
||||
void NetBindComponent::NotifyMigrationStart(ClientInputId migratedInputId)
|
||||
{
|
||||
m_entityMigrationStartEvent.Signal(migratedInputId);
|
||||
}
|
||||
|
||||
void NetBindComponent::NotifyMigrationEnd()
|
||||
{
|
||||
m_entityMigrationEndEvent.Signal();
|
||||
}
|
||||
|
||||
void NetBindComponent::NotifyServerMigration(HostId hostId, AzNetworking::ConnectionId connectionId)
|
||||
{
|
||||
m_entityServerMigrationEvent.Signal(m_netEntityHandle, hostId, connectionId);
|
||||
@@ -428,16 +418,6 @@ namespace Multiplayer
|
||||
eventHandler.Connect(m_syncRewindEvent);
|
||||
}
|
||||
|
||||
void NetBindComponent::AddEntityMigrationStartEventHandler(EntityMigrationStartEvent::Handler& eventHandler)
|
||||
{
|
||||
eventHandler.Connect(m_entityMigrationStartEvent);
|
||||
}
|
||||
|
||||
void NetBindComponent::AddEntityMigrationEndEventHandler(EntityMigrationEndEvent::Handler& eventHandler)
|
||||
{
|
||||
eventHandler.Connect(m_entityMigrationEndEvent);
|
||||
}
|
||||
|
||||
void NetBindComponent::AddEntityServerMigrationEventHandler(EntityServerMigrationEvent::Handler& eventHandler)
|
||||
{
|
||||
eventHandler.Connect(m_entityServerMigrationEvent);
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Multiplayer
|
||||
// This can be used to help mitigate client side performance when large numbers of entities are created off the network
|
||||
AZ_CVAR(uint32_t, cl_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");
|
||||
AZ_CVAR(AZ::TimeMs, cl_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");
|
||||
AZ_CVAR(AZ::TimeMs, cl_DefaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Max Ms to use to activate entities coming from the network, 0 means instantiate everything");
|
||||
|
||||
ClientToServerConnectionData::ClientToServerConnectionData
|
||||
(
|
||||
@@ -26,6 +27,7 @@ namespace Multiplayer
|
||||
{
|
||||
m_entityReplicationManager.SetMaxRemoteEntitiesPendingCreationCount(cl_ClientMaxRemoteEntitiesPendingCreationCount);
|
||||
m_entityReplicationManager.SetEntityPendingRemovalMs(cl_ClientEntityReplicatorPendingRemovalTimeMs);
|
||||
m_entityReplicationManager.SetEntityActivationTimeSliceMs(cl_DefaultNetworkEntityActivationTimeSliceMs);
|
||||
}
|
||||
|
||||
ClientToServerConnectionData::~ClientToServerConnectionData()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Multiplayer/ConnectionData/IConnectionData.h>
|
||||
#include <Source/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Multiplayer/ConnectionData/IConnectionData.h>
|
||||
#include <Source/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Multiplayer
|
||||
{
|
||||
m_networkEditorInterface = AZ::Interface<INetworking>::Get()->CreateNetworkInterface(
|
||||
AZ::Name(MpEditorInterfaceName), ProtocolType::Tcp, TrustZone::ExternalClientToServer, *this);
|
||||
m_networkEditorInterface->SetTimeoutEnabled(false);
|
||||
m_networkEditorInterface->SetTimeoutMs(AZ::TimeMs{ 0 }); // Disable timeouts on this network interface
|
||||
if (editorsv_isDedicated)
|
||||
{
|
||||
uint16_t editorServerPort = DefaultServerEditorPort;
|
||||
|
||||
@@ -10,6 +10,17 @@
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
void FullOwnershipEntityDomain::SetAabb([[maybe_unused]] const AZ::Aabb& aabb)
|
||||
{
|
||||
; // Do nothing, by definition we own everything
|
||||
}
|
||||
|
||||
const AZ::Aabb& FullOwnershipEntityDomain::GetAabb() const
|
||||
{
|
||||
static AZ::Aabb nullAabb = AZ::Aabb::CreateNull();
|
||||
return nullAabb;
|
||||
}
|
||||
|
||||
bool FullOwnershipEntityDomain::IsInDomain([[maybe_unused]] const ConstNetworkEntityHandle& entityHandle) const
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace Multiplayer
|
||||
|
||||
//! IEntityDomain overrides.
|
||||
//! @{
|
||||
void SetAabb(const AZ::Aabb& aabb) override;
|
||||
const AZ::Aabb& GetAabb() const override;
|
||||
bool IsInDomain(const ConstNetworkEntityHandle& entityHandle) const override;
|
||||
void ActivateTracking(const INetworkEntityManager::OwnedEntitySet& ownedEntitySet) override;
|
||||
void RetrieveEntitiesNotInDomain(EntitiesNotInDomain& outEntitiesNotInDomain) const override;
|
||||
|
||||
@@ -79,8 +79,6 @@ namespace Multiplayer
|
||||
AZ_CVAR(ProtocolType, sv_protocol, ProtocolType::Udp, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "This flag controls whether we use TCP or UDP for game networking");
|
||||
AZ_CVAR(bool, sv_isDedicated, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether the host command creates an independent or client hosted server");
|
||||
AZ_CVAR(bool, sv_isTransient, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether a dedicated server shuts down if all existing connections disconnect.");
|
||||
AZ_CVAR(AZ::TimeMs, cl_defaultNetworkEntityActivationTimeSliceMs, AZ::TimeMs{ 0 }, nullptr, AZ::ConsoleFunctorFlags::DontReplicate,
|
||||
"Max Ms to use to activate entities coming from the network, 0 means instantiate everything");
|
||||
AZ_CVAR(AZ::TimeMs, sv_serverSendRateMs, AZ::TimeMs{ 50 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum number of milliseconds between each network update");
|
||||
AZ_CVAR(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset, "prefabs/player.network.spawnable", nullptr, AZ::ConsoleFunctorFlags::DontReplicate,
|
||||
"The default spawnable to use when a new player connects");
|
||||
@@ -94,7 +92,6 @@ namespace Multiplayer
|
||||
{
|
||||
serializeContext->Class<MultiplayerSystemComponent, AZ::Component>()
|
||||
->Version(1);
|
||||
|
||||
serializeContext->Class<HostId>()
|
||||
->Version(1);
|
||||
serializeContext->Class<NetEntityId>()
|
||||
@@ -173,7 +170,12 @@ namespace Multiplayer
|
||||
AZ::ConsoleInvokedFrom invokedFrom
|
||||
) { OnConsoleCommandInvoked(command, args, flags, invokedFrom); })
|
||||
{
|
||||
;
|
||||
AZ::Interface<IMultiplayer>::Register(this);
|
||||
}
|
||||
|
||||
MultiplayerSystemComponent::~MultiplayerSystemComponent()
|
||||
{
|
||||
AZ::Interface<IMultiplayer>::Unregister(this);
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::Activate()
|
||||
@@ -185,7 +187,6 @@ namespace Multiplayer
|
||||
{
|
||||
m_consoleCommandHandler.Connect(AZ::Interface<AZ::IConsole>::Get()->GetConsoleCommandInvokedEvent());
|
||||
}
|
||||
AZ::Interface<IMultiplayer>::Register(this);
|
||||
AZ::Interface<AzFramework::ISessionHandlingClientRequests>::Register(this);
|
||||
|
||||
//! Register our gems multiplayer components to assign NetComponentIds
|
||||
@@ -195,7 +196,6 @@ namespace Multiplayer
|
||||
void MultiplayerSystemComponent::Deactivate()
|
||||
{
|
||||
AZ::Interface<AzFramework::ISessionHandlingClientRequests>::Unregister(this);
|
||||
AZ::Interface<IMultiplayer>::Unregister(this);
|
||||
m_consoleCommandHandler.Disconnect();
|
||||
AZ::Interface<INetworking>::Get()->DestroyNetworkInterface(AZ::Name(MpNetworkInterfaceName));
|
||||
AzFramework::SessionNotificationBus::Handler::BusDisconnect();
|
||||
@@ -459,7 +459,7 @@ namespace Multiplayer
|
||||
AzFramework::PlayerConnectionConfig config;
|
||||
config.m_playerConnectionId = aznumeric_cast<uint32_t>(connection->GetConnectionId());
|
||||
config.m_playerSessionId = packet.GetTicket();
|
||||
if(!AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get()->ValidatePlayerJoinSession(config))
|
||||
if (!AZ::Interface<AzFramework::ISessionHandlingProviderRequests>::Get()->ValidatePlayerJoinSession(config))
|
||||
{
|
||||
auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::TerminatedByUser, TerminationEndpoint::Local); };
|
||||
m_networkInterface->GetConnectionSet().VisitConnections(visitor);
|
||||
@@ -488,10 +488,8 @@ namespace Multiplayer
|
||||
)
|
||||
{
|
||||
m_didHandshake = true;
|
||||
|
||||
AZ::CVarFixedString commandString = "sv_map " + packet.GetMap();
|
||||
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(commandString.c_str());
|
||||
|
||||
AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap();
|
||||
AZ::Interface<AZ::IConsole>::Get()->PerformCommand(loadLevelString.c_str());
|
||||
return true;
|
||||
@@ -606,7 +604,22 @@ namespace Multiplayer
|
||||
[[maybe_unused]] MultiplayerPackets::ClientMigration& packet
|
||||
)
|
||||
{
|
||||
return false;
|
||||
if (GetAgentType() != MultiplayerAgentType::Client)
|
||||
{
|
||||
// Only clients are allowed to migrate from one server to another
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the temporary user identifier so we can transmit it with our next Connect packet
|
||||
// The new server will use this to reattach our set of autonomous entities
|
||||
|
||||
// Disconnect our existing server connection
|
||||
auto visitor = [](IConnection& connection) { connection.Disconnect(DisconnectReason::ClientMigrated, TerminationEndpoint::Local); };
|
||||
m_networkInterface->GetConnectionSet().VisitConnections(visitor);
|
||||
AZLOG_INFO("Migrating to new server shard");
|
||||
//m_clientMigrateStartEvent(packet.GetLastInputGameTimeMs());
|
||||
m_networkInterface->Connect(packet.GetRemoteServerAddress());
|
||||
return true;
|
||||
}
|
||||
|
||||
ConnectResult MultiplayerSystemComponent::ValidateConnect
|
||||
@@ -640,7 +653,7 @@ namespace Multiplayer
|
||||
else
|
||||
{
|
||||
AZLOG_INFO("New incoming connection from remote address: %s", connection->GetRemoteAddress().GetString().c_str());
|
||||
m_connAcquiredEvent.Signal(datum);
|
||||
m_connectionAcquiredEvent.Signal(datum);
|
||||
}
|
||||
|
||||
// Hosts will spawn a new default player prefab for the user that just connected
|
||||
@@ -654,27 +667,14 @@ namespace Multiplayer
|
||||
}
|
||||
controlledEntity.Activate();
|
||||
|
||||
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
|
||||
{
|
||||
connection->SetUserData(new ServerToClientConnectionData(connection, *this, controlledEntity));
|
||||
}
|
||||
|
||||
connection->SetUserData(new ServerToClientConnectionData(connection, *this, controlledEntity));
|
||||
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<ServerToClientReplicationWindow>(controlledEntity, connection);
|
||||
reinterpret_cast<ServerToClientConnectionData*>(connection->GetUserData())->GetReplicationManager().SetReplicationWindow(AZStd::move(window));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (connection->GetUserData() == nullptr) // Only add user data if the connect event handler has not already done so
|
||||
{
|
||||
connection->SetUserData(new ClientToServerConnectionData(connection, *this, providerTicket));
|
||||
}
|
||||
else
|
||||
{
|
||||
reinterpret_cast<ClientToServerConnectionData*>(connection->GetUserData())->SetProviderTicket(providerTicket);
|
||||
}
|
||||
|
||||
connection->SetUserData(new ClientToServerConnectionData(connection, *this, providerTicket));
|
||||
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<NullReplicationWindow>();
|
||||
reinterpret_cast<ClientToServerConnectionData*>(connection->GetUserData())->GetReplicationManager().SetEntityActivationTimeSliceMs(cl_defaultNetworkEntityActivationTimeSliceMs);
|
||||
reinterpret_cast<ClientToServerConnectionData*>(connection->GetUserData())->GetReplicationManager().SetReplicationWindow(AZStd::move(window));
|
||||
}
|
||||
}
|
||||
@@ -757,9 +757,11 @@ namespace Multiplayer
|
||||
{
|
||||
m_initEvent.Signal(m_networkInterface);
|
||||
|
||||
//const AZ::Aabb worldBounds = AZ::Interface<IPhysics>.Get()->GetWorldBounds();
|
||||
AZStd::unique_ptr<IEntityDomain> newDomain = AZStd::make_unique<FullOwnershipEntityDomain>();
|
||||
m_networkEntityManager.Initialize(InvalidHostId, AZStd::move(newDomain));
|
||||
if (!m_networkEntityManager.IsInitialized())
|
||||
{
|
||||
// Set up a full ownership domain if we didn't construct a domain during the initialize event
|
||||
m_networkEntityManager.Initialize(InvalidHostId, AZStd::make_unique<FullOwnershipEntityDomain>());
|
||||
}
|
||||
}
|
||||
}
|
||||
m_agentType = multiplayerType;
|
||||
@@ -778,6 +780,16 @@ namespace Multiplayer
|
||||
AZLOG_INFO("Multiplayer operating in %s mode", GetEnumString(m_agentType));
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::AddClientMigrationStartEventHandler(ClientMigrationStartEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_clientMigrationStartEvent);
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::AddClientMigrationEndEventHandler(ClientMigrationEndEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_clientMigrationEndEvent);
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::AddClientDisconnectedHandler(ClientDisconnectedEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_clientDisconnectedEvent);
|
||||
@@ -785,7 +797,7 @@ namespace Multiplayer
|
||||
|
||||
void MultiplayerSystemComponent::AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_connAcquiredEvent);
|
||||
handler.Connect(m_connectionAcquiredEvent);
|
||||
}
|
||||
|
||||
void MultiplayerSystemComponent::AddSessionInitHandler(SessionInitEvent::Handler& handler)
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Multiplayer
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
|
||||
|
||||
MultiplayerSystemComponent();
|
||||
~MultiplayerSystemComponent() override = default;
|
||||
~MultiplayerSystemComponent() override;
|
||||
|
||||
//! AZ::Component overrides.
|
||||
//! @{
|
||||
@@ -105,13 +105,15 @@ namespace Multiplayer
|
||||
//! @{
|
||||
MultiplayerAgentType GetAgentType() const override;
|
||||
void InitializeMultiplayer(MultiplayerAgentType state) override;
|
||||
bool StartHosting(uint16_t port, bool isDedicated = true) override;
|
||||
bool Connect(AZStd::string remoteAddress, uint16_t port) override;
|
||||
void Terminate(AzNetworking::DisconnectReason reason) override;
|
||||
void AddClientMigrationStartEventHandler(ClientMigrationStartEvent::Handler& handler) override;
|
||||
void AddClientMigrationEndEventHandler(ClientMigrationEndEvent::Handler& handler) override;
|
||||
void AddClientDisconnectedHandler(ClientDisconnectedEvent::Handler& handler) override;
|
||||
void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) override;
|
||||
void AddSessionInitHandler(SessionInitEvent::Handler& handler) override;
|
||||
void AddSessionShutdownHandler(SessionShutdownEvent::Handler& handler) override;
|
||||
bool StartHosting(uint16_t port, bool isDedicated = true) override;
|
||||
bool Connect(AZStd::string remoteAddress, uint16_t port) override;
|
||||
void Terminate(AzNetworking::DisconnectReason reason) override;
|
||||
void SendReadyForEntityUpdates(bool readyForEntityUpdates) override;
|
||||
AZ::TimeMs GetCurrentHostTimeMs() const override;
|
||||
float GetCurrentBlendFactor() const override;
|
||||
@@ -148,8 +150,10 @@ namespace Multiplayer
|
||||
|
||||
SessionInitEvent m_initEvent;
|
||||
SessionShutdownEvent m_shutdownEvent;
|
||||
ConnectionAcquiredEvent m_connAcquiredEvent;
|
||||
ConnectionAcquiredEvent m_connectionAcquiredEvent;
|
||||
ClientDisconnectedEvent m_clientDisconnectedEvent;
|
||||
ClientMigrationStartEvent m_clientMigrationStartEvent;
|
||||
ClientMigrationEndEvent m_clientMigrationEndEvent;
|
||||
|
||||
AZStd::queue<AZStd::string> m_pendingConnectionTickets;
|
||||
|
||||
|
||||
+13
-8
@@ -6,8 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Source/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
#include <Source/NetworkEntity/EntityReplication/EntityReplicator.h>
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.h>
|
||||
#include <Source/NetworkEntity/EntityReplication/PropertyPublisher.h>
|
||||
#include <Source/NetworkEntity/EntityReplication/PropertySubscriber.h>
|
||||
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
|
||||
@@ -444,6 +444,11 @@ namespace Multiplayer
|
||||
handler.Connect(m_autonomousEntityReplicatorCreated);
|
||||
}
|
||||
|
||||
void EntityReplicationManager::AddSendMigrateEntityEventHandler(SendMigrateEntityEvent::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_sendMigrateEntityEvent);
|
||||
}
|
||||
|
||||
const EntityReplicator* EntityReplicationManager::GetEntityReplicator(NetEntityId netEntityId) const
|
||||
{
|
||||
auto it = m_entityReplicatorMap.find(netEntityId);
|
||||
@@ -1094,7 +1099,7 @@ namespace Multiplayer
|
||||
|
||||
bool didSucceed = true;
|
||||
EntityMigrationMessage message;
|
||||
message.m_entityId = replicator->GetEntityHandle().GetNetEntityId();
|
||||
message.m_netEntityId = replicator->GetEntityHandle().GetNetEntityId();
|
||||
message.m_prefabEntityId = netBindComponent->GetPrefabEntityId();
|
||||
|
||||
if (localEnt->GetState() == AZ::Entity::State::Active)
|
||||
@@ -1119,8 +1124,8 @@ namespace Multiplayer
|
||||
message.m_propertyUpdateData.Resize(inputSerializer.GetSize());
|
||||
}
|
||||
AZ_Assert(didSucceed, "Failed to migrate entity from server");
|
||||
// TODO: Move this to an event
|
||||
//m_connection.SendReliablePacket(message);
|
||||
|
||||
m_sendMigrateEntityEvent.Signal(m_connection, message);
|
||||
AZLOG(NET_RepDeletes, "Migration packet sent %u to remote manager id %d", netEntityId, aznumeric_cast<int32_t>(GetRemoteHostId()));
|
||||
|
||||
// Immediately add a new replicator so that we catch RPC invocations, the remote side will make us a new one, and then remove us if needs be
|
||||
@@ -1130,7 +1135,7 @@ namespace Multiplayer
|
||||
|
||||
bool EntityReplicationManager::HandleEntityMigration(AzNetworking::IConnection* invokingConnection, EntityMigrationMessage& message)
|
||||
{
|
||||
EntityReplicator* replicator = GetEntityReplicator(message.m_entityId);
|
||||
EntityReplicator* replicator = GetEntityReplicator(message.m_netEntityId);
|
||||
{
|
||||
if (message.m_propertyUpdateData.GetSize() > 0)
|
||||
{
|
||||
@@ -1140,7 +1145,7 @@ namespace Multiplayer
|
||||
invokingConnection,
|
||||
replicator,
|
||||
AzNetworking::InvalidPacketId,
|
||||
message.m_entityId,
|
||||
message.m_netEntityId,
|
||||
NetEntityRole::Server,
|
||||
outputSerializer,
|
||||
message.m_prefabEntityId
|
||||
@@ -1154,7 +1159,7 @@ namespace Multiplayer
|
||||
// The HandlePropertyChangeMessage will have made a replicator if we didn't have one already
|
||||
if (!replicator)
|
||||
{
|
||||
replicator = GetEntityReplicator(message.m_entityId);
|
||||
replicator = GetEntityReplicator(message.m_netEntityId);
|
||||
}
|
||||
AZ_Assert(replicator, "Do not have replicator after handling migration message");
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Source/NetworkEntity/EntityReplication/EntityReplicator.h>
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.h>
|
||||
#include <Multiplayer/Components/NetBindComponent.h>
|
||||
#include <Multiplayer/EntityDomains/IEntityDomain.h>
|
||||
#include <Multiplayer/NetworkEntity/INetworkEntityManager.h>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Source/NetworkEntity/EntityReplication/EntityReplicator.h>
|
||||
#include <Source/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.h>
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
#include <Source/NetworkEntity/EntityReplication/PropertyPublisher.h>
|
||||
#include <Source/NetworkEntity/EntityReplication/PropertySubscriber.h>
|
||||
#include <Source/NetworkEntity/NetworkEntityAuthorityTracker.h>
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/Event.h>
|
||||
#include <AzCore/EBus/ScheduledEvent.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/EntityBus.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/std/containers/ring_buffer.h>
|
||||
#include <Multiplayer/Components/NetBindComponent.h>
|
||||
#include <Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
class IConnection;
|
||||
}
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
class EntityReplicationManager;
|
||||
class NetworkEntityRpcMessage;
|
||||
class NetBindComponent;
|
||||
|
||||
class PropertyPublisher;
|
||||
class PropertySubscriber;
|
||||
|
||||
class EntityReplicator final
|
||||
: public AZ::EntityBus::Handler
|
||||
{
|
||||
public:
|
||||
EntityReplicator(EntityReplicationManager& replicationManager, AzNetworking::IConnection* connection, NetEntityRole remoteNetworkRole, const ConstNetworkEntityHandle& entityHandle);
|
||||
virtual ~EntityReplicator();
|
||||
|
||||
NetEntityRole GetBoundLocalNetworkRole() const;
|
||||
NetEntityRole GetRemoteNetworkRole() const;
|
||||
ConstNetworkEntityHandle GetEntityHandle() const;
|
||||
NetBindComponent* GetNetBindComponent();
|
||||
|
||||
void ActivateNetworkEntity();
|
||||
|
||||
const PrefabEntityId& GetPrefabEntityId() const;
|
||||
bool IsPrefabEntityIdSet() const;
|
||||
|
||||
bool OwnsReplicatorLifetime() const;
|
||||
bool RemoteManagerOwnsEntityLifetime() const;
|
||||
|
||||
// Interface for ReplicationManager to modify state of replication
|
||||
void Initialize(const ConstNetworkEntityHandle& entityHandle);
|
||||
void Reset(NetEntityRole remoteNetworkRole);
|
||||
void MarkForRemoval();
|
||||
bool IsMarkedForRemoval() const;
|
||||
void SetPendingRemoval(AZ::TimeMs pendingRemovalTimeMs);
|
||||
bool IsPendingRemoval() const;
|
||||
void ClearPendingRemoval();
|
||||
bool IsDeletionAcknowledged() const;
|
||||
bool WasMigrated() const;
|
||||
void SetWasMigrated(bool wasMigrated);
|
||||
|
||||
NetworkEntityUpdateMessage GenerateUpdatePacket();
|
||||
|
||||
AZ::TimeMs GetResendTimeoutTimeMs() const;
|
||||
|
||||
PropertyPublisher* GetPropertyPublisher();
|
||||
const PropertyPublisher* GetPropertyPublisher() const;
|
||||
PropertySubscriber* GetPropertySubscriber();
|
||||
|
||||
// Handlers for Rpc messages
|
||||
bool HandleRpcMessage(AzNetworking::IConnection* invokingConnection, NetworkEntityRpcMessage& entityRpcMessage);
|
||||
|
||||
//! AZ::EntityBus overrides
|
||||
//! @{
|
||||
void OnEntityActivated(const AZ::EntityId&) override;
|
||||
void OnEntityDestroyed(const AZ::EntityId&) override;
|
||||
//! @}
|
||||
|
||||
private:
|
||||
enum class RpcValidationResult
|
||||
{
|
||||
HandleRpc, // Handle Rpc message
|
||||
DropRpc, // Do not handle Rpc
|
||||
DropRpcAndDisconnect, // Do not handle the Rpc, it is disallowed from this endpoint we should disconnect the connection
|
||||
ForwardToClient, // Forward this message to the Client
|
||||
ForwardToAutonomous, // Forward this message to the Autonomous
|
||||
ForwardToAuthority, // Forward this message to the Authority
|
||||
};
|
||||
RpcValidationResult ValidateRpcMessage(const NetworkEntityRpcMessage& entityRpcMessage) const;
|
||||
|
||||
// Internal state tracking
|
||||
bool CanSendUpdates();
|
||||
|
||||
void SetPrefabEntityId(const PrefabEntityId& prefabEntityId); // cache assetId so authority doesn't need to keep sending it
|
||||
|
||||
// Event processing
|
||||
void OnSendRpcEvent(NetworkEntityRpcMessage& message);
|
||||
void OnForwardRpcEvent(NetworkEntityRpcMessage& message);
|
||||
void OnEntityDirtiedEvent();
|
||||
void OnEntityRemovedEvent();
|
||||
void OnProxyRemovalTimedEvent();
|
||||
|
||||
void ActivateNetworkEntityInternal();
|
||||
|
||||
void AttachRPCHandlers();
|
||||
|
||||
void DeferRpcMessage(NetworkEntityRpcMessage& message);
|
||||
|
||||
AZ_DISABLE_COPY_MOVE(EntityReplicator);
|
||||
|
||||
// Events
|
||||
RpcSendEvent::Handler m_onSendRpcHandler;
|
||||
RpcSendEvent::Handler m_onForwardRpcHandler;
|
||||
RpcSendEvent::Handler m_onSendAutonomousRpcHandler;
|
||||
RpcSendEvent::Handler m_onForwardAutonomousRpcHandler;
|
||||
EntityDirtiedEvent::Handler m_onEntityDirtiedHandler;
|
||||
EntityStopEvent::Handler m_onEntityStopHandler;
|
||||
AZ::ScheduledEvent m_proxyRemovalEvent;
|
||||
|
||||
ConstNetworkEntityHandle m_entityHandle;
|
||||
PrefabEntityId m_prefabEntityId;
|
||||
|
||||
AZStd::unique_ptr<PropertyPublisher> m_propertyPublisher;
|
||||
AZStd::unique_ptr<PropertySubscriber> m_propertySubscriber;
|
||||
|
||||
NetBindComponent* m_netBindComponent = nullptr;
|
||||
EntityReplicationManager& m_replicationManager;
|
||||
AzNetworking::IConnection* m_connection;
|
||||
NetEntityRole m_boundLocalNetworkRole;
|
||||
NetEntityRole m_remoteNetworkRole;
|
||||
|
||||
bool m_wasMigrated = false;
|
||||
bool m_isForwardingRpc = false;
|
||||
bool m_prefabEntityIdSet = false;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Source/NetworkEntity/EntityReplication/EntityReplicator.inl>
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
inline NetEntityRole EntityReplicator::GetBoundLocalNetworkRole() const
|
||||
{
|
||||
return m_boundLocalNetworkRole;
|
||||
}
|
||||
|
||||
inline NetEntityRole EntityReplicator::GetRemoteNetworkRole() const
|
||||
{
|
||||
return m_remoteNetworkRole;
|
||||
}
|
||||
|
||||
inline ConstNetworkEntityHandle EntityReplicator::GetEntityHandle() const
|
||||
{
|
||||
return m_entityHandle;
|
||||
}
|
||||
|
||||
inline NetBindComponent* EntityReplicator::GetNetBindComponent()
|
||||
{
|
||||
return m_netBindComponent;
|
||||
}
|
||||
|
||||
inline const PrefabEntityId& EntityReplicator::GetPrefabEntityId() const
|
||||
{
|
||||
AZ_Assert(IsPrefabEntityIdSet(), "PrefabEntityId not set for Entity");
|
||||
return m_prefabEntityId;
|
||||
}
|
||||
|
||||
inline bool EntityReplicator::IsPrefabEntityIdSet() const
|
||||
{
|
||||
return m_prefabEntityIdSet;
|
||||
}
|
||||
|
||||
inline bool EntityReplicator::WasMigrated() const
|
||||
{
|
||||
return m_wasMigrated;
|
||||
}
|
||||
|
||||
inline void EntityReplicator::SetWasMigrated(bool wasMigrated)
|
||||
{
|
||||
m_wasMigrated = wasMigrated;
|
||||
}
|
||||
|
||||
inline PropertyPublisher* EntityReplicator::GetPropertyPublisher()
|
||||
{
|
||||
return m_propertyPublisher.get();
|
||||
}
|
||||
|
||||
inline const PropertyPublisher* EntityReplicator::GetPropertyPublisher() const
|
||||
{
|
||||
return m_propertyPublisher.get();
|
||||
}
|
||||
|
||||
inline PropertySubscriber* EntityReplicator::GetPropertySubscriber()
|
||||
{
|
||||
return m_propertySubscriber.get();
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <Source/NetworkEntity/EntityReplication/PropertySubscriber.h>
|
||||
#include <Source/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicationManager.h>
|
||||
#include <Multiplayer/Components/NetBindComponent.h>
|
||||
|
||||
namespace Multiplayer
|
||||
|
||||
@@ -48,6 +48,16 @@ namespace Multiplayer
|
||||
m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true);
|
||||
}
|
||||
|
||||
bool NetworkEntityManager::IsInitialized() const
|
||||
{
|
||||
return m_entityDomain != nullptr;
|
||||
}
|
||||
|
||||
IEntityDomain* NetworkEntityManager::GetEntityDomain() const
|
||||
{
|
||||
return m_entityDomain.get();
|
||||
}
|
||||
|
||||
NetworkEntityTracker* NetworkEntityManager::GetNetworkEntityTracker()
|
||||
{
|
||||
return &m_networkEntityTracker;
|
||||
|
||||
@@ -31,11 +31,11 @@ namespace Multiplayer
|
||||
NetworkEntityManager();
|
||||
~NetworkEntityManager();
|
||||
|
||||
//! Only invoked for authoritative hosts
|
||||
void Initialize(HostId hostId, AZStd::unique_ptr<IEntityDomain> entityDomain);
|
||||
|
||||
//! INetworkEntityManager overrides.
|
||||
//! @{
|
||||
void Initialize(HostId hostId, AZStd::unique_ptr<IEntityDomain> entityDomain) override;
|
||||
bool IsInitialized() const override;
|
||||
IEntityDomain* GetEntityDomain() const override;
|
||||
NetworkEntityTracker* GetNetworkEntityTracker() override;
|
||||
NetworkEntityAuthorityTracker* GetNetworkEntityAuthorityTracker() override;
|
||||
MultiplayerComponentRegistry* GetMultiplayerComponentRegistry() override;
|
||||
|
||||
Reference in New Issue
Block a user