Various bug fixes to get entity replication working

This commit is contained in:
karlberg
2021-04-13 20:24:08 -07:00
parent 7b3b1cd73e
commit ca3df5d6c8
29 changed files with 495 additions and 137 deletions
@@ -25,6 +25,7 @@
#include <AzNetworking/PacketLayer/IPacketHeader.h>
#include <AzNetworking/Serialization/NetworkInputSerializer.h>
#include <AzNetworking/Serialization/NetworkOutputSerializer.h>
#include <AzNetworking/Serialization/TrackChangedSerializer.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/Console/ILogger.h>
@@ -126,9 +127,9 @@ namespace Multiplayer
MultiplayerPackets::EntityUpdates entityUpdatePacket;
entityUpdatePacket.SetHostTimeMs(serverGameTimeMs);
// Serialize everything
for (auto it = toSendList.begin(); it != toSendList.end();)
while (!toSendList.empty())
{
EntityReplicator* replicator = *it;
EntityReplicator* replicator = toSendList.front();
NetworkEntityUpdateMessage updateMessage(replicator->GenerateUpdatePacket());
const uint32_t nextMessageSize = updateMessage.GetEstimatedSerializeSize();
@@ -144,15 +145,15 @@ namespace Multiplayer
pendingPacketSize += nextMessageSize;
entityUpdatePacket.ModifyEntityMessages().push_back(updateMessage);
replicatorUpdatedList.push_back(*it);
it = toSendList.erase(it);
replicatorUpdatedList.push_back(replicator);
toSendList.pop_front();
if (largeEntityDetected)
{
AZLOG_WARN("\n\n*******************************");
AZLOG_WARN
(
"Serializing Extremely Large Entity (%u) - MaxPayload: %d NeededSize %d",
"Serializing extremely large entity (%u) - MaxPayload: %d NeededSize %d",
aznumeric_cast<uint32_t>(replicator->GetEntityHandle().GetNetEntityId()),
maxPayloadSize,
nextMessageSize
@@ -173,16 +174,16 @@ namespace Multiplayer
EntityReplicationManager::EntityReplicatorList EntityReplicationManager::GenerateEntityUpdateList()
{
if (m_replicationWindow == nullptr)
{
return EntityReplicatorList();
}
// Generate a list of all our entities that need updates
EntityReplicatorList autonomousReplicators;
autonomousReplicators.reserve(m_replicatorsPendingSend.size());
EntityReplicatorList proxyReplicators;
proxyReplicators.reserve(m_replicatorsPendingSend.size());
EntityReplicatorList toSendList;
uint32_t elementsAdded = 0;
for (auto iter = m_replicatorsPendingSend.begin();
iter != m_replicatorsPendingSend.end()
&& elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount();)
for (auto iter = m_replicatorsPendingSend.begin(); iter != m_replicatorsPendingSend.end() && elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount(); )
{
EntityReplicator* replicator = GetEntityReplicator(*iter);
bool clearPendingSend = true;
@@ -218,13 +219,13 @@ namespace Multiplayer
if (replicator->GetRemoteNetworkRole() == NetEntityRole::Autonomous)
{
autonomousReplicators.push_back(replicator);
toSendList.push_back(replicator);
}
else
{
if (elementsAdded < m_replicationWindow->GetMaxEntityReplicatorSendCount())
{
proxyReplicators.push_back(replicator);
toSendList.push_back(replicator);
}
}
}
@@ -243,9 +244,6 @@ namespace Multiplayer
}
}
EntityReplicatorList toSendList;
toSendList.swap(autonomousReplicators);
toSendList.insert(toSendList.end(), proxyReplicators.begin(), proxyReplicators.end());
return toSendList;
}
@@ -543,6 +541,7 @@ namespace Multiplayer
// Create an entity if we don't have one
if (createEntity)
{
// @pereslav
//replicatorEntity = GetNetworkEntityManager()->CreateSingleEntityImmediateInternal(prefabEntityId, EntitySpawnType::Replicate, AutoActivate::DoNotActivate, netEntityId, localNetworkRole, AZ::Transform::Identity());
AZ_Assert(replicatorEntity != nullptr, "Failed to create entity from prefab");// %s", prefabEntityId.GetString());
if (replicatorEntity == nullptr)
@@ -765,7 +764,7 @@ namespace Multiplayer
return HandleEntityDeleteMessage(entityReplicator, packetHeader, updateMessage);
}
AzNetworking::NetworkOutputSerializer outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize());
AzNetworking::TrackChangedSerializer<AzNetworking::NetworkOutputSerializer> outputSerializer(updateMessage.GetData()->GetBuffer(), updateMessage.GetData()->GetSize());
PrefabEntityId prefabEntityId;
if (updateMessage.GetHasValidPrefabId())
@@ -1125,7 +1124,7 @@ namespace Multiplayer
{
if (message.GetPropertyUpdateData().GetSize() > 0)
{
AzNetworking::NetworkOutputSerializer outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize());
AzNetworking::TrackChangedSerializer<AzNetworking::NetworkOutputSerializer> outputSerializer(message.ModifyPropertyUpdateData().GetBuffer(), message.ModifyPropertyUpdateData().GetSize());
if (!HandlePropertyChangeMessage
(
replicator,
@@ -22,6 +22,7 @@
#include <AzNetworking/PacketLayer/IPacketHeader.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/deque.h>
#include <AzCore/std/limits.h>
#include <AzCore/EBus/Event.h>
#include <AzCore/EBus/ScheduledEvent.h>
@@ -114,7 +115,7 @@ namespace Multiplayer
using RpcMessages = AZStd::list<NetworkEntityRpcMessage>;
bool DispatchOrphanedRpc(NetworkEntityRpcMessage& message, EntityReplicator* entityReplicator);
using EntityReplicatorList = AZStd::vector<EntityReplicator*>;
using EntityReplicatorList = AZStd::deque<EntityReplicator*>;
EntityReplicatorList GenerateEntityUpdateList();
void SendEntityUpdatesPacketHelper(AZ::TimeMs serverGameTimeMs, EntityReplicatorList& toSendList, uint32_t maxPayloadSize, AzNetworking::IConnection& connection);
@@ -283,7 +283,7 @@ namespace Multiplayer
AZ_Assert(netBindComponent, "No Multiplayer::NetBindComponent");
bool isAuthority = (GetBoundLocalNetworkRole() == NetEntityRole::Authority)
&& (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole());
&& (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole());
bool isClient = GetRemoteNetworkRole() == NetEntityRole::Client;
bool isAutonomous = GetBoundLocalNetworkRole() == NetEntityRole::Autonomous;
if (isAuthority || isClient || isAutonomous)
@@ -311,9 +311,9 @@ namespace Multiplayer
{
bool ret(false);
bool isServer = (GetBoundLocalNetworkRole() == NetEntityRole::Server)
&& (GetRemoteNetworkRole() == NetEntityRole::Authority);
&& (GetRemoteNetworkRole() == NetEntityRole::Authority);
bool isClient = (GetBoundLocalNetworkRole() == NetEntityRole::Client)
|| (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous);
|| (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous);
if (isServer || isClient)
{
ret = true;
@@ -12,6 +12,7 @@
#include <Source/NetworkEntity/NetworkEntityManager.h>
#include <Source/Components/NetBindComponent.h>
#include <Include/IMultiplayer.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/Console/ILogger.h>
@@ -34,6 +35,12 @@ namespace Multiplayer
, m_entityRemovedEventHandler([this](AZ::Entity* entity) { OnEntityRemoved(entity); })
{
AZ::Interface<INetworkEntityManager>::Register(this);
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
{
// Null guard needed for unit tests
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler);
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler);
}
}
NetworkEntityManager::~NetworkEntityManager()
@@ -43,13 +50,6 @@ namespace Multiplayer
void NetworkEntityManager::Initialize(HostId hostId, AZStd::unique_ptr<IEntityDomain> entityDomain)
{
if (AZ::Interface<AZ::ComponentApplicationRequests>::Get() != nullptr)
{
// Null guard needed for unit tests
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityAddedEventHandler(m_entityAddedEventHandler);
AZ::Interface<AZ::ComponentApplicationRequests>::Get()->RegisterEntityRemovedEventHandler(m_entityRemovedEventHandler);
}
m_hostId = hostId;
m_entityDomain = AZStd::move(entityDomain);
m_updateEntityDomainEvent.Enqueue(net_EntityDomainUpdateMs, true);
@@ -282,8 +282,13 @@ namespace Multiplayer
NetBindComponent* netBindComponent = entity->FindComponent<NetBindComponent>();
if (netBindComponent != nullptr)
{
// @pereslav
// Note that this is a total hack.. we should not be listening to this event on a client
// Entities should instead be spawned by the prefabEntityId inside EntityReplicationManager::HandlePropertyChangeMessage()
const bool isClient = AZ::Interface<IMultiplayer>::Get()->GetAgentType() == MultiplayerAgentType::Client;
const NetEntityRole netEntityRole = isClient ? NetEntityRole::Client: NetEntityRole::Authority;
const NetEntityId netEntityId = m_nextEntityId++;
netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, NetEntityRole::Authority);
netBindComponent->PreInit(entity, PrefabEntityId(), netEntityId, netEntityRole);
}
}