Fixes and cleanup for recent correction changes

Signed-off-by: kberg-amzn <karlberg@amazon.com>
This commit is contained in:
kberg-amzn
2021-08-09 16:17:23 -07:00
parent d0394ec3fc
commit f85e8124a9
8 changed files with 36 additions and 103 deletions
@@ -14,8 +14,6 @@
namespace Multiplayer
{
using CorrectionEvent = AZ::Event<>;
class LocalPredictionPlayerInputComponent
: public LocalPredictionPlayerInputComponentBase
{
@@ -65,8 +63,6 @@ namespace Multiplayer
ClientInputId GetLastInputId() const;
HostFrameId GetInputFrameId(const NetworkInput& input) const;
void CorrectionEventAddHandle(CorrectionEvent::Handler& handler);
private:
void OnMigrateStart(ClientInputId migratedInputId);
@@ -86,7 +82,6 @@ namespace Multiplayer
AZ::ScheduledEvent m_autonomousUpdateEvent; // Drives autonomous input collection
AZ::ScheduledEvent m_updateBankedTimeEvent; // Drives authority bank time updates
CorrectionEvent m_correctionEvent;
EntityMigrationStartEvent::Handler m_migrateStartHandler;
EntityMigrationEndEvent::Handler m_migrateEndHandler;
@@ -36,6 +36,7 @@ namespace Multiplayer
using EntityMigrationEndEvent = AZ::Event<>;
using EntityServerMigrationEvent = AZ::Event<const ConstNetworkEntityHandle&, HostId, AzNetworking::ConnectionId>;
using EntityPreRenderEvent = AZ::Event<float, float>;
using EntityCorrectionEvent = AZ::Event<>;
//! @class NetBindComponent
//! @brief Component that provides net-binding to a networked entity.
@@ -118,6 +119,7 @@ namespace Multiplayer
void NotifyMigrationEnd();
void NotifyServerMigration(HostId hostId, AzNetworking::ConnectionId connectionId);
void NotifyPreRender(float deltaTime, float blendFactor);
void NotifyCorrection();
void AddEntityStopEventHandler(EntityStopEvent::Handler& eventHandler);
void AddEntityDirtiedEventHandler(EntityDirtiedEvent::Handler& eventHandler);
@@ -126,6 +128,7 @@ namespace Multiplayer
void AddEntityMigrationEndEventHandler(EntityMigrationEndEvent::Handler& eventHandler);
void AddEntityServerMigrationEventHandler(EntityServerMigrationEvent::Handler& eventHandler);
void AddEntityPreRenderEventHandler(EntityPreRenderEvent::Handler& eventHandler);
void AddEntityCorrectionEventHandler(EntityCorrectionEvent::Handler& handler);
bool SerializeEntityCorrection(AzNetworking::ISerializer& serializer);
@@ -175,6 +178,7 @@ namespace Multiplayer
EntityMigrationEndEvent m_entityMigrationEndEvent;
EntityServerMigrationEvent m_entityServerMigrationEvent;
EntityPreRenderEvent m_entityPreRenderEvent;
EntityCorrectionEvent m_entityCorrectionEvent;
AZ::Event<> m_onRemove;
RpcSendEvent::Handler m_handleLocalServerRpcMessageEventHandle;
AZ::Event<>::Handler m_handleMarkedDirty;
@@ -30,6 +30,7 @@ namespace Multiplayer
private:
void OnPreRender(float deltaTime, float blendFactor);
void OnCorrection();
void OnRotationChangedEvent(const AZ::Quaternion& rotation);
void OnTranslationChangedEvent(const AZ::Vector3& translation);
@@ -47,6 +48,7 @@ namespace Multiplayer
AZ::Event<uint8_t>::Handler m_resetCountEventHandler;
EntityPreRenderEvent::Handler m_entityPreRenderEventHandler;
EntityCorrectionEvent::Handler m_entityCorrectionEventHandler;
Multiplayer::HostFrameId m_targetHostFrameId = HostFrameId(0);
};
@@ -32,21 +32,6 @@ namespace Multiplayer
AZ_CVAR(AZ::TimeMs, sv_MinCorrectionTimeMs, AZ::TimeMs{ 100 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum time to wait between sending out corrections in order to avoid flooding corrections on high-latency connections");
AZ_CVAR(AZ::TimeMs, sv_InputUpdateTimeMs, AZ::TimeMs{ 5 }, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum time between component updates");
// Debug helper functions
AZStd::string GetInputString(NetworkInput& input)
{
AzNetworking::StringifySerializer serializer(',', false);
input.Serialize(serializer);
return serializer.GetString();
}
AZStd::string GetCorrectionDataString(NetBindComponent* netBindComponent)
{
AzNetworking::StringifySerializer serializer(',', false);
netBindComponent->SerializeEntityCorrection(serializer);
return serializer.GetString();
}
void PrintCorrectionDifferences(const AzNetworking::StringifySerializer& client, const AzNetworking::StringifySerializer& server)
{
const auto& clientMap = client.GetValueMap();
@@ -289,14 +274,7 @@ namespace Multiplayer
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId());
GetNetBindComponent()->ProcessInput(input, clientInputRateSec);
AZLOG
(
NET_Prediction,
"Migrated InputId=%d - i=[%s] o=[%s]",
aznumeric_cast<int32_t>(input.GetClientInputId()),
GetInputString(input).c_str(),
GetCorrectionDataString(GetNetBindComponent()).c_str()
);
AZLOG(NET_Prediction, "Migrated InputId=%d", aznumeric_cast<int32_t>(input.GetClientInputId()));
// Don't bother checking for corrections here, the next regular input will trigger any corrections if necessary
// Also don't bother with any cheat detection here, because the input array is limited in size and at most and can only be sent once
@@ -329,7 +307,7 @@ namespace Multiplayer
// Apply the correction
AzNetworking::TrackChangedSerializer<AzNetworking::NetworkOutputSerializer> serializer(correction.GetBuffer(), correction.GetSize());
GetNetBindComponent()->SerializeEntityCorrection(serializer);
m_correctionEvent.Signal();
GetNetBindComponent()->NotifyCorrection();
#ifndef AZ_RELEASE_BUILD
if (cl_EnableDesyncDebugging)
@@ -350,14 +328,6 @@ namespace Multiplayer
}
#endif
AZLOG
(
NET_Prediction,
"Corrected InputId=%d - o=[%s]",
aznumeric_cast<int32_t>(m_lastCorrectionInputId),
GetCorrectionDataString(GetNetBindComponent()).c_str()
);
const uint32_t inputHistorySize = m_inputHistory.Size();
const uint32_t historicalDelta = aznumeric_cast<uint32_t>(m_clientInputId - inputId); // Do not replay the move we just corrected, that was already processed by the server
@@ -372,14 +342,7 @@ namespace Multiplayer
ScopedAlterTime scopedTime(input.GetHostFrameId(), input.GetHostTimeMs(), input.GetHostBlendFactor(), invokingConnection->GetConnectionId());
GetNetBindComponent()->ReprocessInput(input, clientInputRateSec);
AZLOG
(
NET_Prediction,
"Replayed InputId=%d - i=[%s] o=[%s]",
aznumeric_cast<int32_t>(input.GetClientInputId()),
GetInputString(input).c_str(),
GetCorrectionDataString(GetNetBindComponent()).c_str()
);
AZLOG(NET_Prediction, "Replayed InputId=%d", aznumeric_cast<int32_t>(input.GetClientInputId()));
}
}
@@ -402,11 +365,6 @@ namespace Multiplayer
return (input.GetHostFrameId() == InvalidHostFrameId) ? m_serverMigrateFrameId : input.GetHostFrameId();
}
void LocalPredictionPlayerInputComponentController::CorrectionEventAddHandle(CorrectionEvent::Handler& handler)
{
handler.Connect(m_correctionEvent);
}
void LocalPredictionPlayerInputComponentController::OnMigrateStart(ClientInputId migratedInputId)
{
m_lastMigratedInputId = migratedInputId;
@@ -480,14 +438,7 @@ namespace Multiplayer
// Process the input for this frame
GetNetBindComponent()->ProcessInput(input, inputRate);
AZLOG
(
NET_Prediction,
"Processed InutId=%d - i=[%s] o=[%s]",
aznumeric_cast<int32_t>(m_clientInputId),
GetInputString(input).c_str(),
GetCorrectionDataString(GetNetBindComponent()).c_str()
);
AZLOG(NET_Prediction, "Processed InputId=%d", aznumeric_cast<int32_t>(m_clientInputId));
// Generate a hash based on the current client predicted states
AzNetworking::HashSerializer hashSerializer;
@@ -553,14 +504,7 @@ namespace Multiplayer
GetNetBindComponent()->ProcessInput(input, inputRate);
}
AZLOG
(
NET_Prediction,
"Forced InputId=%d - i=[%s] o=[%s]",
aznumeric_cast<int32_t>(input.GetClientInputId()),
GetInputString(input).c_str(),
GetCorrectionDataString(GetNetBindComponent()).c_str()
);
AZLOG(NET_Prediction, "Forced InputId=%d", aznumeric_cast<int32_t>(input.GetClientInputId()));
}
// Decay our bank time window, in case the remote endpoint has suffered a more persistent shift in latency, this should cause the client to eventually recover
@@ -408,6 +408,11 @@ namespace Multiplayer
m_entityPreRenderEvent.Signal(deltaTime, blendFactor);
}
void NetBindComponent::NotifyCorrection()
{
m_entityCorrectionEvent.Signal();
}
void NetBindComponent::AddEntityStopEventHandler(EntityStopEvent::Handler& eventHandler)
{
eventHandler.Connect(m_entityStopEvent);
@@ -443,6 +448,11 @@ namespace Multiplayer
eventHandler.Connect(m_entityPreRenderEvent);
}
void NetBindComponent::AddEntityCorrectionEventHandler(EntityCorrectionEvent::Handler& eventHandler)
{
eventHandler.Connect(m_entityCorrectionEvent);
}
bool NetBindComponent::SerializeEntityCorrection(AzNetworking::ISerializer& serializer)
{
m_predictableRecord.ResetConsumedBits();
@@ -31,6 +31,7 @@ namespace Multiplayer
, m_scaleEventHandler([this](float scale) { OnScaleChangedEvent(scale); })
, m_resetCountEventHandler([this](const uint8_t&) { OnResetCountChangedEvent(); })
, m_entityPreRenderEventHandler([this](float deltaTime, float blendFactor) { OnPreRender(deltaTime, blendFactor); })
, m_entityCorrectionEventHandler([this]() { OnCorrection(); })
{
;
}
@@ -47,6 +48,7 @@ namespace Multiplayer
ScaleAddEvent(m_scaleEventHandler);
ResetCountAddEvent(m_resetCountEventHandler);
GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler);
GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler);
// When coming into relevance, reset all blending factors so we don't interpolate to our start position
OnResetCountChangedEvent();
@@ -119,6 +121,18 @@ namespace Multiplayer
}
}
void NetworkTransformComponent::OnCorrection()
{
// Snap to latest
OnResetCountChangedEvent();
// Hard set the entities transform
if (!GetTransformComponent()->GetWorldTM().IsClose(m_targetTransform))
{
GetTransformComponent()->SetWorldTM(m_targetTransform);
}
}
NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent)
: NetworkTransformComponentControllerBase(parent)