Fixes to sending entity updates and entity rpcs within an environment set up for cross host entity migration

Signed-off-by: kberg-amzn <karlberg@amazon.com>
monroegm-disable-blank-issue-2
kberg-amzn 4 years ago
parent 0a829f9661
commit 02bc89cd92

@ -40,8 +40,7 @@ namespace Multiplayer
virtual EntityReplicationManager& GetReplicationManager() = 0;
//! Creates and manages sending updates to the remote endpoint.
//! @param hostTimeMs current server game time in milliseconds
virtual void Update(AZ::TimeMs hostTimeMs) = 0;
virtual void Update() = 0;
//! Returns whether update messages can be sent to the connection.
//! @return true if update messages can be sent

@ -60,7 +60,7 @@ namespace Multiplayer
const HostId& GetRemoteHostId() const;
void ActivatePendingEntities();
void SendUpdates(AZ::TimeMs hostTimeMs);
void SendUpdates();
void Clear(bool forMigration);
bool SetEntityRebasing(NetworkEntityHandle& entityHandle);
@ -81,7 +81,7 @@ namespace Multiplayer
void AddDeferredRpcMessage(NetworkEntityRpcMessage& rpcMessage);
void AddAutonomousEntityReplicatorCreatedHandle(AZ::Event<NetEntityId>::Handler& handler);
void AddAutonomousEntityReplicatorCreatedHandler(AZ::Event<NetEntityId>::Handler& handler);
void AddSendMigrateEntityEventHandler(SendMigrateEntityEvent::Handler& handler);
bool HandleEntityMigration(AzNetworking::IConnection* invokingConnection, EntityMigrationMessage& message);
@ -120,10 +120,8 @@ namespace Multiplayer
using EntityReplicatorList = AZStd::deque<EntityReplicator*>;
EntityReplicatorList GenerateEntityUpdateList();
void SendEntityUpdatesPacketHelper(AZ::TimeMs hostTimeMs, EntityReplicatorList& toSendList, uint32_t maxPayloadSize, AzNetworking::IConnection& connection);
void SendEntityUpdates(AZ::TimeMs hostTimeMs);
void SendEntityRpcs(RpcMessages& deferredRpcs, bool reliable);
void SendEntityUpdateMessages(EntityReplicatorList& replicatorList);
void SendEntityRpcs(RpcMessages& rpcMessages, bool reliable);
void MigrateEntityInternal(NetEntityId entityId);
void OnEntityExitDomain(const ConstNetworkEntityHandle& entityHandle);

@ -66,6 +66,7 @@ namespace Multiplayer
bool IsReadyToActivate() const;
NetworkEntityUpdateMessage GenerateUpdatePacket();
void FinalizeSerialization(AzNetworking::PacketId sentId);
AZ::TimeMs GetResendTimeoutTimeMs() const;

@ -103,6 +103,7 @@ namespace Multiplayer
// Non-serialized RPC metadata
ReliabilityType m_isReliable = ReliabilityType::Reliable;
};
using NetworkEntityRpcVector = AZStd::fixed_vector<NetworkEntityRpcMessage, MaxAggregateRpcMessages>;
struct IRpcParamStruct
{

@ -118,4 +118,5 @@ namespace Multiplayer
// This is to prevent blowing out stack memory if we declare an array of these EntityUpdateMessages
AZStd::unique_ptr<AzNetworking::PacketEncodingBuffer> m_data;
};
using NetworkEntityUpdateVector = AZStd::fixed_vector<NetworkEntityUpdateMessage, MaxAggregateEntityMessages>;
}

@ -10,10 +10,14 @@
#include <Multiplayer/MultiplayerTypes.h>
#include <Multiplayer/NetworkEntity/NetworkEntityHandle.h>
#include <Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h>
#include <Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h>
#include <AzCore/std/containers/map.h>
namespace Multiplayer
{
class EntityReplicator;
struct EntityReplicationData
{
EntityReplicationData() = default;
@ -21,6 +25,8 @@ namespace Multiplayer
float m_priority = 0.0f;
};
using ReplicationSet = AZStd::map<ConstNetworkEntityHandle, EntityReplicationData>;
using RpcMessages = AZStd::list<NetworkEntityRpcMessage>;
using EntityReplicatorList = AZStd::deque<EntityReplicator*>;
class IReplicationWindow
{
@ -33,6 +39,8 @@ namespace Multiplayer
virtual uint32_t GetMaxProxyEntityReplicatorSendCount() const = 0;
virtual bool IsInWindow(const ConstNetworkEntityHandle& entityPtr, NetEntityRole& outNetworkRole) const = 0;
virtual void UpdateWindow() = 0;
virtual AzNetworking::PacketId SendEntityUpdateMessages(NetworkEntityUpdateVector& entityUpdateVector) = 0;
virtual void SendEntityRpcs(NetworkEntityRpcVector& entityRpcVector, bool reliable) = 0;
virtual void DebugDraw() const = 0;
};
}

@ -15,7 +15,7 @@
<Packet Name="Accept" HandshakePacket="true" Desc="Server accept packet">
<Member Type="Multiplayer::LongNetworkString" Name="map" />
</Packet>
<Packet Name="ReadyForEntityUpdates" Desc="Client confirming it is ready to receive entity updates">
<Member Type="bool" Name="readyForEntityUpdates" />
</Packet>
@ -31,11 +31,11 @@
<Packet Name="EntityUpdates" Desc="A packet that contains multiple entity updates">
<Member Type="AZ::TimeMs" Name="hostTimeMs" Init="AZ::TimeMs{ 0 }" />
<Member Type="Multiplayer::HostFrameId" Name="hostFrameId" Init="Multiplayer::InvalidHostFrameId" />
<Member Type="Multiplayer::NetworkEntityUpdateMessage" Name="entityMessages" Container="Vector" Count="Multiplayer::MaxAggregateEntityMessages" />
<Member Type="Multiplayer::NetworkEntityUpdateVector" Name="entityMessages" />
</Packet>
<Packet Name="EntityRpcs" Desc="A packet that contains multiple entity rpcs">
<Member Type="Multiplayer::NetworkEntityRpcMessage" Name="entityRpcs" Container="Vector" Count="Multiplayer::MaxAggregateRpcMessages" />
<Member Type="Multiplayer::NetworkEntityRpcVector" Name="entityRpcs" />
</Packet>
<Packet Name="ClientMigration" Desc="Tell a client to migrate to a new server">

@ -50,9 +50,9 @@ namespace Multiplayer
return m_entityReplicationManager;
}
void ClientToServerConnectionData::Update(AZ::TimeMs hostTimeMs)
void ClientToServerConnectionData::Update()
{
m_entityReplicationManager.ActivatePendingEntities();
m_entityReplicationManager.SendUpdates(hostTimeMs);
m_entityReplicationManager.SendUpdates();
}
}

@ -30,7 +30,7 @@ namespace Multiplayer
ConnectionDataType GetConnectionDataType() const override;
AzNetworking::IConnection* GetConnection() const override;
EntityReplicationManager& GetReplicationManager() override;
void Update(AZ::TimeMs hostTimeMs) override;
void Update() override;
bool CanSendUpdates() const override;
void SetCanSendUpdates(bool canSendUpdates) override;
//! @}

@ -69,7 +69,7 @@ namespace Multiplayer
return m_entityReplicationManager;
}
void ServerToClientConnectionData::Update(AZ::TimeMs hostTimeMs)
void ServerToClientConnectionData::Update()
{
m_entityReplicationManager.ActivatePendingEntities();
@ -79,7 +79,7 @@ namespace Multiplayer
// potentially false if we just migrated the player, if that is the case, don't send any more updates
if (netBindComponent != nullptr && (netBindComponent->GetNetEntityRole() == NetEntityRole::Authority))
{
m_entityReplicationManager.SendUpdates(hostTimeMs);
m_entityReplicationManager.SendUpdates();
}
}
}

@ -30,7 +30,7 @@ namespace Multiplayer
ConnectionDataType GetConnectionDataType() const override;
AzNetworking::IConnection* GetConnection() const override;
EntityReplicationManager& GetReplicationManager() override;
void Update(AZ::TimeMs hostTimeMs) override;
void Update() override;
bool CanSendUpdates() const override;
void SetCanSendUpdates(bool canSendUpdates) override;
//! @}

@ -307,7 +307,6 @@ namespace Multiplayer
void MultiplayerSystemComponent::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
const AZ::TimeMs deltaTimeMs = aznumeric_cast<AZ::TimeMs>(static_cast<int32_t>(deltaTime * 1000.0f));
const AZ::TimeMs hostTimeMs = AZ::GetElapsedTimeMs();
const AZ::TimeMs serverRateMs = static_cast<AZ::TimeMs>(sv_serverSendRateMs);
const float serverRateSeconds = static_cast<float>(serverRateMs) / 1000.0f;
@ -344,12 +343,12 @@ namespace Multiplayer
// Send out the game state update to all connections
{
auto sendNetworkUpdates = [hostTimeMs, &stats](IConnection& connection)
auto sendNetworkUpdates = [&stats](IConnection& connection)
{
if (connection.GetUserData() != nullptr)
{
IConnectionData* connectionData = reinterpret_cast<IConnectionData*>(connection.GetUserData());
connectionData->Update(hostTimeMs);
connectionData->Update();
if (connectionData->GetConnectionDataType() == ConnectionDataType::ServerToClient)
{
stats.m_clientConnectionCount++;
@ -671,7 +670,7 @@ namespace Multiplayer
else
{
connection->SetUserData(new ClientToServerConnectionData(connection, *this, providerTicket));
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<NullReplicationWindow>();
AZStd::unique_ptr<IReplicationWindow> window = AZStd::make_unique<NullReplicationWindow>(connection);
reinterpret_cast<ClientToServerConnectionData*>(connection->GetUserData())->GetReplicationManager().SetReplicationWindow(AZStd::move(window));
}
}

@ -10,7 +10,6 @@
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.h>
#include <Source/NetworkEntity/EntityReplication/PropertyPublisher.h>
#include <Source/NetworkEntity/EntityReplication/PropertySubscriber.h>
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
#include <Multiplayer/IMultiplayer.h>
#include <Multiplayer/Components/NetBindComponent.h>
#include <Multiplayer/EntityDomains/IEntityDomain.h>
@ -107,10 +106,34 @@ namespace Multiplayer
}
}
void EntityReplicationManager::SendUpdates(AZ::TimeMs hostTimeMs)
void EntityReplicationManager::SendUpdates()
{
m_frameTimeMs = AZ::GetElapsedTimeMs();
SendEntityUpdates(hostTimeMs);
{
EntityReplicatorList toSendList = GenerateEntityUpdateList();
AZLOG
(
NET_ReplicationInfo,
"Sending %zd updates from %s to %s",
toSendList.size(),
GetNetworkEntityManager()->GetHostId().GetString().c_str(),
GetRemoteHostId().GetString().c_str()
);
// Prep a replication record for send, at this point, everything needs to be sent
for (EntityReplicator* replicator : toSendList)
{
replicator->GetPropertyPublisher()->PrepareSerialization();
}
// While our to send list is not empty, build up another packet to send
do
{
SendEntityUpdateMessages(toSendList);
} while (!toSendList.empty());
}
SendEntityRpcs(m_deferredRpcMessagesReliable, true);
SendEntityRpcs(m_deferredRpcMessagesUnreliable, false);
@ -130,65 +153,6 @@ namespace Multiplayer
);
}
void EntityReplicationManager::SendEntityUpdatesPacketHelper
(
AZ::TimeMs hostTimeMs,
EntityReplicatorList& toSendList,
uint32_t maxPayloadSize,
AzNetworking::IConnection& connection
)
{
uint32_t pendingPacketSize = 0;
EntityReplicatorList replicatorUpdatedList;
MultiplayerPackets::EntityUpdates entityUpdatePacket;
entityUpdatePacket.SetHostTimeMs(hostTimeMs);
entityUpdatePacket.SetHostFrameId(GetNetworkTime()->GetHostFrameId());
// Serialize everything
while (!toSendList.empty())
{
EntityReplicator* replicator = toSendList.front();
NetworkEntityUpdateMessage updateMessage(replicator->GenerateUpdatePacket());
const uint32_t nextMessageSize = updateMessage.GetEstimatedSerializeSize();
// Check if we are over our limits
const bool payloadFull = (pendingPacketSize + nextMessageSize > maxPayloadSize);
const bool capacityReached = (entityUpdatePacket.GetEntityMessages().size() >= entityUpdatePacket.GetEntityMessages().capacity());
const bool largeEntityDetected = (payloadFull && replicatorUpdatedList.empty());
if (capacityReached || (payloadFull && !largeEntityDetected))
{
break;
}
pendingPacketSize += nextMessageSize;
entityUpdatePacket.ModifyEntityMessages().push_back(updateMessage);
replicatorUpdatedList.push_back(replicator);
toSendList.pop_front();
if (largeEntityDetected)
{
AZLOG_WARN("\n\n*******************************");
AZLOG_WARN
(
"Serializing extremely large entity (%u) - MaxPayload: %d NeededSize %d",
aznumeric_cast<uint32_t>(replicator->GetEntityHandle().GetNetEntityId()),
maxPayloadSize,
nextMessageSize
);
AZLOG_WARN("*******************************");
break;
}
}
const AzNetworking::PacketId sentId = connection.SendUnreliablePacket(entityUpdatePacket);
// Update the sent things with the packet id
for (EntityReplicator* replicator : replicatorUpdatedList)
{
replicator->GetPropertyPublisher()->FinalizeSerialization(sentId);
}
}
EntityReplicationManager::EntityReplicatorList EntityReplicationManager::GenerateEntityUpdateList()
{
if (m_replicationWindow == nullptr)
@ -260,76 +224,92 @@ namespace Multiplayer
return toSendList;
}
void EntityReplicationManager::SendEntityUpdates(AZ::TimeMs hostTimeMs)
void EntityReplicationManager::SendEntityUpdateMessages(EntityReplicatorList& replicatorList)
{
EntityReplicatorList toSendList = GenerateEntityUpdateList();
uint32_t pendingPacketSize = 0;
EntityReplicatorList replicatorUpdatedList;
NetworkEntityUpdateVector entityUpdates;
// Serialize everything
while (!replicatorList.empty())
{
EntityReplicator* replicator = replicatorList.front();
NetworkEntityUpdateMessage updateMessage(replicator->GenerateUpdatePacket());
AZLOG
(
NET_ReplicationInfo,
"Sending %zd updates from %s to %s",
toSendList.size(),
GetNetworkEntityManager()->GetHostId().GetString().c_str(),
GetRemoteHostId().GetString().c_str()
);
const uint32_t nextMessageSize = updateMessage.GetEstimatedSerializeSize();
// prep a replication record for send, at this point, everything needs to be sent
for (EntityReplicator* replicator : toSendList)
{
replicator->GetPropertyPublisher()->PrepareSerialization();
// Check if we are over our limits
const bool payloadFull = (pendingPacketSize + nextMessageSize > m_maxPayloadSize);
const bool capacityReached = (entityUpdates.size() >= entityUpdates.capacity());
const bool largeEntityDetected = (payloadFull && replicatorUpdatedList.empty());
if (capacityReached || (payloadFull && !largeEntityDetected))
{
break;
}
pendingPacketSize += nextMessageSize;
entityUpdates.push_back(updateMessage);
replicatorUpdatedList.push_back(replicator);
replicatorList.pop_front();
if (largeEntityDetected)
{
AZLOG_WARN
(
"Serializing extremely large entity (%u) - MaxPayload: %d NeededSize %d",
aznumeric_cast<uint32_t>(replicator->GetEntityHandle().GetNetEntityId()),
m_maxPayloadSize,
nextMessageSize
);
break;
}
}
// While our to send list is not empty, build up another packet to send
do
const AzNetworking::PacketId sentId = m_replicationWindow->SendEntityUpdateMessages(entityUpdates);
// Update the sent things with the packet id
for (EntityReplicator* replicator : replicatorUpdatedList)
{
SendEntityUpdatesPacketHelper(hostTimeMs, toSendList, m_maxPayloadSize, m_connection);
} while (!toSendList.empty());
replicator->FinalizeSerialization(sentId);
}
}
void EntityReplicationManager::SendEntityRpcs(RpcMessages& deferredRpcs, bool reliable)
void EntityReplicationManager::SendEntityRpcs(RpcMessages& rpcMessages, bool reliable)
{
while (!deferredRpcs.empty())
while (!rpcMessages.empty())
{
MultiplayerPackets::EntityRpcs entityRpcsPacket;
NetworkEntityRpcVector entityRpcs;
uint32_t pendingPacketSize = 0;
while (!deferredRpcs.empty())
while (!rpcMessages.empty())
{
NetworkEntityRpcMessage& message = deferredRpcs.front();
NetworkEntityRpcMessage& message = rpcMessages.front();
const uint32_t nextRpcSize = message.GetEstimatedSerializeSize();
if ((pendingPacketSize + nextRpcSize) > m_maxPayloadSize)
{
// We're over our limit, break and send an Rpc packet
if (entityRpcsPacket.GetEntityRpcs().size() == 0)
if (entityRpcs.size() == 0)
{
AZLOG(NET_Replicator, "Encountered an RPC that is above our MTU, message will be segmented (object size %u, max allowed size %u)", nextRpcSize, m_maxPayloadSize);
entityRpcsPacket.ModifyEntityRpcs().push_back(message);
deferredRpcs.pop_front();
entityRpcs.push_back(message);
rpcMessages.pop_front();
}
break;
}
pendingPacketSize += nextRpcSize;
if (entityRpcsPacket.GetEntityRpcs().full())
if (entityRpcs.full())
{
// Packet was full, send what we've accumulated so far
AZLOG(NET_Replicator, "We've hit our RPC message limit (RPC count %u, packet size %u)", aznumeric_cast<uint32_t>(entityRpcsPacket.GetEntityRpcs().size()), pendingPacketSize);
AZLOG(NET_Replicator, "We've hit our RPC message limit (RPC count %u, packet size %u)", aznumeric_cast<uint32_t>(entityRpcs.size()), pendingPacketSize);
break;
}
entityRpcsPacket.ModifyEntityRpcs().push_back(message);
deferredRpcs.pop_front();
entityRpcs.push_back(message);
rpcMessages.pop_front();
}
if (reliable)
{
m_connection.SendReliablePacket(entityRpcsPacket);
}
else
{
m_connection.SendUnreliablePacket(entityRpcsPacket);
}
m_replicationWindow->SendEntityRpcs(entityRpcs, reliable);
}
}
@ -474,7 +454,7 @@ namespace Multiplayer
}
// @nt: TODO - delete once dropped RPC problem fixed
void EntityReplicationManager::AddAutonomousEntityReplicatorCreatedHandle(AZ::Event<NetEntityId>::Handler& handler)
void EntityReplicationManager::AddAutonomousEntityReplicatorCreatedHandler(AZ::Event<NetEntityId>::Handler& handler)
{
handler.Connect(m_autonomousEntityReplicatorCreated);
}

@ -79,7 +79,7 @@ namespace Multiplayer
void AddDeferredRpcMessage(NetworkEntityRpcMessage& rpcMessage);
void AddAutonomousEntityReplicatorCreatedHandle(AZ::Event<NetEntityId>::Handler& handler);
void AddAutonomousEntityReplicatorCreatedHandler(AZ::Event<NetEntityId>::Handler& handler);
bool HandleEntityMigration(AzNetworking::IConnection* invokingConnection, EntityMigrationMessage& message);
bool HandleEntityDeleteMessage(EntityReplicator* entityReplicator, const AzNetworking::IPacketHeader& packetHeader, const NetworkEntityUpdateMessage& updateMessage);
@ -117,10 +117,8 @@ namespace Multiplayer
using EntityReplicatorList = AZStd::deque<EntityReplicator*>;
EntityReplicatorList GenerateEntityUpdateList();
void SendEntityUpdatesPacketHelper(AZ::TimeMs hostTimeMs, EntityReplicatorList& toSendList, uint32_t maxPayloadSize, AzNetworking::IConnection& connection);
void SendEntityUpdates(AZ::TimeMs hostTimeMs);
void SendEntityRpcs(RpcMessages& deferredRpcs, bool reliable);
void SendEntityUpdateMessages(EntityReplicatorList& replicatorList);
void SendEntityRpcs(RpcMessages& rpcMessages, bool reliable);
void MigrateEntityInternal(NetEntityId entityId);
void OnEntityExitDomain(const ConstNetworkEntityHandle& entityHandle);

@ -14,7 +14,6 @@
#include <Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h>
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.h>
#include <Multiplayer/NetworkEntity/EntityReplication/EntityReplicationManager.h>
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
#include <Source/NetworkEntity/NetworkEntityAuthorityTracker.h>
#include <Source/NetworkEntity/NetworkEntityTracker.h>
#include <Source/NetworkEntity/EntityReplication/PropertyPublisher.h>
@ -495,6 +494,11 @@ namespace Multiplayer
return updateMessage;
}
void EntityReplicator::FinalizeSerialization(AzNetworking::PacketId sentId)
{
m_propertyPublisher->FinalizeSerialization(sentId);
}
void EntityReplicator::DeferRpcMessage(NetworkEntityRpcMessage& entityRpcMessage)
{
// Received rpc metrics, log rpc sent, number of bytes, and the componentId/rpcId for bandwidth metrics

@ -336,7 +336,6 @@ namespace Multiplayer
case PropertyPublisher::EntityReplicatorState::Deleting:
{
AZ_Assert(m_serializationPhase == PropertyPublisher::EntityReplicatorSerializationPhase::Prepared, "Unexpected serialization phase");
FinalizeDeleteEntityRecord(sentId);
}
break;

@ -7,9 +7,16 @@
*/
#include <Source/ReplicationWindows/NullReplicationWindow.h>
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
namespace Multiplayer
{
NullReplicationWindow::NullReplicationWindow(AzNetworking::IConnection* connection)
: m_connection(connection)
{
;
}
bool NullReplicationWindow::ReplicationSetUpdateReady()
{
return true;
@ -36,6 +43,29 @@ namespace Multiplayer
;
}
AzNetworking::PacketId NullReplicationWindow::SendEntityUpdateMessages(NetworkEntityUpdateVector& entityUpdateVector)
{
MultiplayerPackets::EntityUpdates entityUpdatePacket;
entityUpdatePacket.SetHostTimeMs(GetNetworkTime()->GetHostTimeMs());
entityUpdatePacket.SetHostFrameId(GetNetworkTime()->GetHostFrameId());
entityUpdatePacket.SetEntityMessages(entityUpdateVector);
return m_connection->SendUnreliablePacket(entityUpdatePacket);
}
void NullReplicationWindow::SendEntityRpcs(NetworkEntityRpcVector& entityRpcVector, bool reliable)
{
MultiplayerPackets::EntityRpcs entityRpcsPacket;
entityRpcsPacket.SetEntityRpcs(entityRpcVector);
if (reliable)
{
m_connection->SendReliablePacket(entityRpcsPacket);
}
else
{
m_connection->SendUnreliablePacket(entityRpcsPacket);
}
}
void NullReplicationWindow::DebugDraw() const
{
// Nothing to draw

@ -9,6 +9,7 @@
#pragma once
#include <Multiplayer/ReplicationWindows/IReplicationWindow.h>
#include <AzNetworking/ConnectionLayer/IConnection.h>
namespace Multiplayer
{
@ -16,7 +17,7 @@ namespace Multiplayer
: public IReplicationWindow
{
public:
NullReplicationWindow() = default;
NullReplicationWindow(AzNetworking::IConnection* connection);
//! IReplicationWindow interface
//! @{
@ -25,10 +26,13 @@ namespace Multiplayer
uint32_t GetMaxProxyEntityReplicatorSendCount() const override;
bool IsInWindow(const ConstNetworkEntityHandle& entityPtr, NetEntityRole& outNetworkRole) const override;
void UpdateWindow() override;
AzNetworking::PacketId SendEntityUpdateMessages(NetworkEntityUpdateVector& entityUpdateVector) override;
void SendEntityRpcs(NetworkEntityRpcVector& entityRpcVector, bool reliable) override;
void DebugDraw() const override;
//! @}
private:
ReplicationSet m_emptySet;
AzNetworking::IConnection* m_connection = nullptr;
};
}

@ -7,6 +7,7 @@
*/
#include <Source/ReplicationWindows/ServerToClientReplicationWindow.h>
#include <Source/AutoGen/Multiplayer.AutoPackets.h>
#include <Multiplayer/Components/NetBindComponent.h>
#include <AzFramework/Visibility/IVisibilitySystem.h>
#include <AzCore/Component/TransformBus.h>
@ -50,7 +51,7 @@ namespace Multiplayer
return m_priority < rhs.m_priority;
}
ServerToClientReplicationWindow::ServerToClientReplicationWindow(NetworkEntityHandle controlledEntity, const AzNetworking::IConnection* connection)
ServerToClientReplicationWindow::ServerToClientReplicationWindow(NetworkEntityHandle controlledEntity, AzNetworking::IConnection* connection)
: m_controlledEntity(controlledEntity)
, m_entityActivatedEventHandler([this](AZ::Entity* entity) { OnEntityActivated(entity); })
, m_entityDeactivatedEventHandler([this](AZ::Entity* entity) { OnEntityDeactivated(entity); })
@ -179,6 +180,29 @@ namespace Multiplayer
//}
}
AzNetworking::PacketId ServerToClientReplicationWindow::SendEntityUpdateMessages(NetworkEntityUpdateVector& entityUpdateVector)
{
MultiplayerPackets::EntityUpdates entityUpdatePacket;
entityUpdatePacket.SetHostTimeMs(GetNetworkTime()->GetHostTimeMs());
entityUpdatePacket.SetHostFrameId(GetNetworkTime()->GetHostFrameId());
entityUpdatePacket.SetEntityMessages(entityUpdateVector);
return m_connection->SendUnreliablePacket(entityUpdatePacket);
}
void ServerToClientReplicationWindow::SendEntityRpcs(NetworkEntityRpcVector& entityRpcVector, bool reliable)
{
MultiplayerPackets::EntityRpcs entityRpcsPacket;
entityRpcsPacket.SetEntityRpcs(entityRpcVector);
if (reliable)
{
m_connection->SendReliablePacket(entityRpcsPacket);
}
else
{
m_connection->SendUnreliablePacket(entityRpcsPacket);
}
}
void ServerToClientReplicationWindow::DebugDraw() const
{
//static const float BoundaryStripeHeight = 1.0f;

@ -38,7 +38,7 @@ namespace Multiplayer
// we sort lowest priority first, so that we can easily keep the biggest N priorities
using ReplicationCandidateQueue = AZStd::priority_queue<PrioritizedReplicationCandidate>;
ServerToClientReplicationWindow(NetworkEntityHandle controlledEntity, const AzNetworking::IConnection* connection);
ServerToClientReplicationWindow(NetworkEntityHandle controlledEntity, AzNetworking::IConnection* connection);
//! IReplicationWindow interface
//! @{
@ -47,6 +47,8 @@ namespace Multiplayer
uint32_t GetMaxProxyEntityReplicatorSendCount() const override;
bool IsInWindow(const ConstNetworkEntityHandle& entityPtr, NetEntityRole& outNetworkRole) const override;
void UpdateWindow() override;
AzNetworking::PacketId SendEntityUpdateMessages(NetworkEntityUpdateVector& entityUpdateVector) override;
void SendEntityRpcs(NetworkEntityRpcVector& entityRpcVector, bool reliable) override;
void DebugDraw() const override;
//! @}
@ -75,7 +77,7 @@ namespace Multiplayer
//NetBindComponent* m_controlledNetBindComponent = nullptr;
const AzNetworking::IConnection* m_connection = nullptr;
AzNetworking::IConnection* m_connection = nullptr;
// Cached values to detect a poor network connection
uint32_t m_lastCheckedSentPackets = 0;

@ -33,6 +33,9 @@ set(FILES
Include/Multiplayer/MultiplayerConstants.h
Include/Multiplayer/MultiplayerStats.h
Include/Multiplayer/MultiplayerTypes.h
Include/Multiplayer/NetworkEntity/EntityReplication/EntityReplicationManager.h
Include/Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.h
Include/Multiplayer/NetworkEntity/EntityReplication/EntityReplicator.inl
Include/Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h
Include/Multiplayer/NetworkEntity/IFilterEntityManager.h
Include/Multiplayer/NetworkEntity/INetworkEntityManager.h

Loading…
Cancel
Save