Merging last dev

Signed-off-by: Gene Walters <genewalt@amazon.com>
This commit is contained in:
Gene Walters
2021-11-19 23:12:59 -08:00
2657 changed files with 249197 additions and 30535 deletions
+13 -31
View File
@@ -86,44 +86,24 @@ ly_create_alias(NAME Multiplayer.Servers NAMESPACE Gem TARGETS Gem::Multiplayer
if (PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_target(
NAME Multiplayer.Builders.Static STATIC
NAME Multiplayer.Tools.Static STATIC
NAMESPACE Gem
FILES_CMAKE
multiplayer_tools_files.cmake
COMPILE_DEFINITIONS
PUBLIC
MULTIPLAYER_TOOLS
INCLUDE_DIRECTORIES
PRIVATE
.
Source
${pal_source_dir}
PUBLIC
Include
BUILD_DEPENDENCIES
PUBLIC
AZ::AzToolsFramework
Gem::Multiplayer.Static
)
# by naming this target Multiplayer.Builders it ensures that it is loaded
# in any pipeline tools (Like Asset Processor, AssetBuilder, etc)
ly_add_target(
NAME Multiplayer.Builders GEM_MODULE
NAMESPACE Gem
FILES_CMAKE
multiplayer_tools_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
AZ::AzNetworking
Source
.
PUBLIC
Include
BUILD_DEPENDENCIES
PRIVATE
Gem::Multiplayer.Builders.Static
RUNTIME_DEPENDENCIES
Gem::Multiplayer.Editor
PUBLIC
AZ::AzCore
AZ::AzFramework
AZ::AzNetworking
AZ::AzToolsFramework
)
ly_add_target(
@@ -152,11 +132,12 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS)
Gem::Atom_RPI.Public
Gem::Atom_RHI.Reflect
Gem::Multiplayer.Static
Gem::Multiplayer.Builders
Gem::Multiplayer.Tools.Static
)
ly_create_alias(NAME Multiplayer.Builders NAMESPACE Gem TARGETS Gem::Multiplayer.Editor)
# use the Multiplayer.Editor module in tools like the Editor: Such tools also get the visual debug view:
ly_create_alias(NAME Multiplayer.Tools NAMESPACE Gem TARGETS Gem::Multiplayer.Editor Gem::Multiplayer.Debug Gem::Multiplayer.Builders)
ly_create_alias(NAME Multiplayer.Tools NAMESPACE Gem TARGETS Gem::Multiplayer.Debug Gem::Multiplayer.Builders)
endif()
if (PAL_TRAIT_BUILD_TESTS_SUPPORTED)
@@ -207,7 +188,8 @@ if (PAL_TRAIT_BUILD_TESTS_SUPPORTED)
AZ::AzTest
AZ::AzTestShared
AZ::AzToolsFrameworkTestCommon
Gem::Multiplayer.Builders.Static
Gem::Multiplayer.Static
Gem::Multiplayer.Tools.Static
)
ly_add_googletest(
NAME Gem::Multiplayer.Builders.Tests
@@ -443,35 +443,31 @@ namespace {{ Component.attrib['Namespace'] }}
{{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', false)|indent(8) -}}
{{ DeclareNetworkPropertyAccessors(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Client', 'Authority', false)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Client', 'Authority', true)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Autonomous', 'Authority', false)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Authority', 'Autonomous', false)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Authority', 'Autonomous', true)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Authority', 'Client', false)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Authority', 'Client', true)|indent(8) -}}
//! RPC Handlers: Override handlers in order to implement what happens after receiving an RPC
{{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Server', 'Authority', false)|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Client', 'Authority', false)|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Autonomous', 'Authority', false)|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Authority', 'Autonomous', false)|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcSignals(Component, 'Server', 'Authority')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcSignals(Component, 'Client', 'Authority')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcSignals(Component, 'Autonomous', 'Authority')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcSignals(Component, 'Authority', 'Autonomous')|indent(8) -}}
//! RPC Event Getters: Subscribe to these events and get notified when an RPC is received
{{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Server', 'Authority')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Client', 'Authority')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Autonomous', 'Authority')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Authority', 'Autonomous')|indent(8) }}
{{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Authority', 'Autonomous')|indent(8) -}}
{% for Service in Component.iter('ComponentRelation') %}
{% if (Service.attrib['HasController']|booleanTrue) and (Service.attrib['Constraint'] != 'Incompatible') %}
{{ Service.attrib['Namespace'] }}::{{ Service.attrib['Name'] }}Controller* Get{{ Service.attrib['Name'] }}Controller();
{% endif %}
{% endfor %}
protected:
{{ AutoComponentMacros.DeclareRpcEvents(Component, 'Server', 'Authority')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcEvents(Component, 'Client', 'Authority')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcEvents(Component, 'Autonomous', 'Authority')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcEvents(Component, 'Authority', 'Autonomous')|indent(8) }}
};
@@ -517,6 +513,8 @@ namespace {{ Component.attrib['Namespace'] }}
{{ DeclareNetworkPropertyGetters(Component, 'Autonomous', 'Authority', false)|indent(8) -}}
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) -}}
//! RPC Event Getters: Subscribe to these events and get notified when this component receives an RPC
{{ AutoComponentMacros.DeclareRpcEventGetters(Component, 'Authority', 'Client')|indent(8) -}}
//! MultiplayerComponent interface
@@ -541,9 +539,13 @@ namespace {{ Component.attrib['Namespace'] }}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', true)|indent(8) -}}
{{ DeclareNetworkPropertyGetters(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|indent(8) -}}
//! RPC Handlers: Override handlers in order to implement what happens after receiving an RPC
{{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Authority', 'Client', false)|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcSignals(Component, 'Authority', 'Client')|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcEvents(Component, 'Authority', 'Client')|indent(8) }}
//! RPC Events: Subscribe to these events and get notified when an RPC is received
{{ AutoComponentMacros.DeclareRpcEvents(Component, 'Authority', 'Client')|indent(8) -}}
{% for Service in Component.iter('ComponentRelation') %}
{% if Service.attrib['Constraint'] != 'Incompatible' %}
const {{ Service.attrib['Namespace'] }}::{{ Service.attrib['Name'] }}* Get{{ Service.attrib['Name'] }}() const;
@@ -308,13 +308,21 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(const {{ Prop
{% endmacro %}
{#
#}
{% macro PrintRpcParameters(printPrefix, paramDefines) %}
{% if paramDefines|count > 0 %}
{{ printPrefix }}{{ ', '.join(paramDefines) }}
{% endif %}
{% endmacro %}
{#
#}
{% macro DefineRpcInvocation(Component, ClassName, Property, InvokeFrom, HandleOn) %}
{% set paramNames = [] %}
{% set paramTypes = [] %}
{% set paramDefines = [] %}
{{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }}
void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramDefines) }})
void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ PrintRpcParameters('', paramDefines) }})
{
constexpr Multiplayer::RpcIndex rpcId = static_cast<Multiplayer::RpcIndex>({{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ UpperFirst(Property.attrib['Name']) }});
{% if Property.attrib['IsReliable']|booleanTrue %}
@@ -340,27 +348,11 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(par
{% endmacro %}
{#
#}
{% macro DefineRpcSignal(Component, ClassName, Property, InvokeFrom) %}
{% set paramNames = [] %}
{% set paramTypes = [] %}
{% set paramDefines = [] %}
{{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }}
void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramDefines) }})
{
m_{{ UpperFirst(Property.attrib['Name']) }}Event.Signal({{ ', '.join(paramNames) }});
}
{% endmacro %}
{#
#}
{% macro DefineRpcInvocations(Component, ClassName, InvokeFrom, HandleOn, IsProtected) %}
{% call(Property) AutoComponentMacros.ParseRemoteProcedures(Component, InvokeFrom, HandleOn) %}
{% if Property.attrib['IsPublic']|booleanTrue != IsProtected %}
{{ DefineRpcInvocation(Component, ClassName, Property, InvokeFrom, HandleOn) -}}
{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %}
{{ DefineRpcSignal(Component, ClassName, Property, InvokeFrom) -}}
{% endif %}
{% endif %}
{% endcall %}
{% endmacro %}
@@ -374,33 +366,46 @@ void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.jo
{% set paramTypes = [] %}
{% set paramDefines = [] %}
{{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }}
->Method("{{ UpperFirst(Property.attrib['Name']) }}", [](const {{ ClassName }}* self, {{ ', '.join(paramDefines) }}) {
self->m_controller->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }});
->Method("{{ UpperFirst(Property.attrib['Name']) }}", []({{ ClassName }}* self{{ PrintRpcParameters(', ', paramDefines) }}) {
{% if (InvokeFrom == 'Server') %}
self->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }});
{% elif (InvokeFrom == 'Authority') or (InvokeFrom == 'Autonomous') %}
if (self->m_controller)
{
self->m_controller->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }});
}
else
{
AZ_Warning("Network RPC", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }} method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This remote-procedure can only be invoked from {{InvokeFrom}} network entities, because this entity doesn't have a controller, it must not be a {{InvokeFrom}} entity. Please check your network context before attempting to call {{ UpperFirst(Property.attrib['Name']) }}.", self->GetEntity()->GetName().c_str(), self->GetEntityId().ToString().c_str())
}
{% endif %}
})
->Method("{{ UpperFirst(Property.attrib['Name']) }}ByEntityId", [](AZ::EntityId id, {{ ', '.join(paramDefines) }}) {
->Method("{{ UpperFirst(Property.attrib['Name']) }}ByEntityId", [](AZ::EntityId id{{ PrintRpcParameters(', ', paramDefines) }}) {
AZ::Entity* entity = AZ::Interface<AZ::ComponentApplicationRequests>::Get()->FindEntity(id);
if (!entity)
{
AZ_Warning("Network Property", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
AZ_Warning("Network RPC", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId failed. The entity with id %s doesn't exist, please provide a valid entity id.", id.ToString().c_str())
return;
}
{{ ClassName }}* networkComponent = entity->FindComponent<{{ ClassName }}>();
if (!networkComponent)
{
AZ_Warning("Network Property", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str())
AZ_Warning("Network RPC", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str())
return;
}
{% if (InvokeFrom == 'Server') %}
networkComponent->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }});
{% elif (InvokeFrom == 'Authority') or (InvokeFrom == 'Autonomous') %}
{{ ClassName }}Controller* controller = static_cast<{{ ClassName }}Controller*>(networkComponent->GetController());
if (!controller)
{
AZ_Warning("Network Property", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This RemoteProcedure can only be invoked from {{InvokeFrom}} network entities, because this entity doesn't have a controller, it must not be a {{InvokeFrom}} entity. Please check your network context before attempting to call {{ UpperFirst(Property.attrib['Name']) }}.", entity->GetName().c_str(), id.ToString().c_str())
AZ_Warning("Network RPC", false, "{{ ClassName }} {{ UpperFirst(Property.attrib['Name']) }}ByEntityId method failed. Entity '%s' (id: %s) {{ ClassName }} is missing the network controller. This RemoteProcedure can only be invoked from {{InvokeFrom}} network entities, because this entity doesn't have a controller, it must not be a {{InvokeFrom}} entity. Please check your network context before attempting to call {{ UpperFirst(Property.attrib['Name']) }}.", entity->GetName().c_str(), id.ToString().c_str())
return;
}
controller->{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(paramNames) }});
{% endif %}
}, { { { "Source", "The Source containing the {{ ClassName }}Controller" }{% for paramName in paramNames %}, {"{{ paramName }}"}{% endfor %}}})
->Attribute(AZ::Script::Attributes::ToolTip, "{{Property.attrib['Description']}}")
{% endif %}
@@ -436,9 +441,13 @@ void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.jo
{% set paramTypes = [] %}
{% set paramDefines = [] %}
{{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }}
->Method("Get{{ UpperFirst(Property.attrib['Name']) }}Event", [](const {{ ClassName }}* self) -> AZ::Event<{{ ', '.join(paramTypes) }}>&
->Method("Get{{ UpperFirst(Property.attrib['Name']) }}Event", []({{ ClassName }}* self) -> AZ::Event<{{ ', '.join(paramTypes) }}>&
{
{% if HandleOn == 'Client' %}
return self->Get{{ UpperFirst(Property.attrib['Name']) }}Event();
{% elif (HandleOn == 'Authority') or (HandleOn == 'Autonomous') %}
return self->m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event();
{% endif %}
})
->Attribute(AZ::Script::Attributes::AzEventDescription, {{ LowerFirst(Property.attrib['Name']) }}EventDesc)
->Method("Get{{ UpperFirst(Property.attrib['Name']) }}EventByEntityId", [](AZ::EntityId id) -> AZ::Event<{{ ', '.join(paramTypes) }}>*
@@ -456,7 +465,9 @@ void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.jo
AZ_Warning("Network Property", false, "{{ ClassName }} Get{{ UpperFirst(Property.attrib['Name']) }}EventByEntityId failed. Entity '%s' (id: %s) is missing {{ ClassName }}, be sure to add {{ ClassName }} to this entity.", entity->GetName().c_str(), id.ToString().c_str())
return nullptr;
}
{% if HandleOn == 'Client' %}
return &networkComponent->Get{{ UpperFirst(Property.attrib['Name']) }}Event();
{% elif (HandleOn == 'Authority') or (HandleOn == 'Autonomous') %}
{{ ClassName }}Controller* controller = static_cast<{{ ClassName }}Controller*>(networkComponent->GetController());
if (!controller)
{
@@ -465,6 +476,7 @@ void {{ ClassName }}::Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.jo
}
return &controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event();
{% endif %}
})
->Attribute(AZ::Script::Attributes::AzEventDescription, AZStd::move({{ LowerFirst(Property.attrib['Name']) }}EventDesc))
{% endif %}
@@ -493,30 +505,32 @@ case {{ UpperFirst(Component.attrib['Name']) }}Internal::RemoteProcedure::{{ Upp
if (m_controller)
{
AZ_Assert(GetNetBindComponent()->GetNetEntityRole() == Multiplayer::NetEntityRole::Authority, "Entity proxy does not have authority");
m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }});
{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %}
m_controller->Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(rpcParamList) }});
{% endif %}
m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection{{ PrintRpcParameters(', ', rpcParamList) }});
{% if (Property.attrib['GenerateEventBindings']|booleanTrue == true) %}
m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ PrintRpcParameters('', rpcParamList) }});
{% endif %}
}
{% if Property.attrib['IsReliable']|booleanTrue %}
{# if the rpc is not reliable we can simply drop it, also note message reliability type is default reliable in EntityRpcMessage #}
else // Note that this rpc is marked reliable, trigger the appropriate rpc event so it can be forwarded
{
{% if Property.attrib['IsReliable']|booleanTrue %}
{# if the rpc is not reliable we can simply drop it, also note message reliability type is default reliable in EntityRpcMessage #}
m_netBindComponent->{{ "GetSend" + InvokeFrom + "To" + HandleOn + "RpcEvent" }}().Signal(message);
{% endif %}
}
{% endif %}
{% elif HandleOn == 'Autonomous' %}
if (m_controller)
{
AZ_Assert(GetNetBindComponent()->GetNetEntityRole() == Multiplayer::NetEntityRole::Autonomous, "Entity proxy does not have autonomy");
m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }});
{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %}
m_controller->Signal{{ UpperFirst(Property.attrib['Name']) }}({{ ', '.join(rpcParamList) }});
{% endif %}
m_controller->Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection{{ PrintRpcParameters(', ', rpcParamList) }});
{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %}
m_controller->Get{{ UpperFirst(Property.attrib['Name']) }}Event().Signal({{ PrintRpcParameters('', rpcParamList) }});
{% endif %}
}
{% else %}
Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection, {{ ', '.join(rpcParamList) }});
{% elif HandleOn == 'Client' %}
Handle{{ UpperFirst(Property.attrib['Name']) }}(invokingConnection{{ PrintRpcParameters(', ', rpcParamList) }});
{% if Property.attrib['GenerateEventBindings']|booleanTrue == true %}
m_{{ UpperFirst(Property.attrib['Name']) }}Event.Signal({{ PrintRpcParameters('', rpcParamList) }});
{% endif %}
{% endif %}
}
else if (paramsSerialized)
@@ -99,8 +99,8 @@ namespace Multiplayer
double m_moveAccumulator = 0.0;
double m_clientBankedTime = 0.0;
AZ::TimeMs m_lastInputReceivedTimeMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_lastCorrectionSentTimeMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_lastInputReceivedTimeMs = AZ::Time::ZeroTimeMs;
AZ::TimeMs m_lastCorrectionSentTimeMs = AZ::Time::ZeroTimeMs;
ClientInputId m_clientInputId = ClientInputId{ 0 }; // Clients incrementing inputId
ClientInputId m_lastClientInputId = ClientInputId{ 0 }; // Last inputId processed by the server
@@ -265,7 +265,7 @@ namespace Multiplayer
}
private:
HostFrameId m_previousHostFrameId = InvalidHostFrameId;
AZ::TimeMs m_previousHostTimeMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_previousHostTimeMs = AZ::Time::ZeroTimeMs;
AzNetworking::ConnectionId m_previousRewindConnectionId = AzNetworking::InvalidConnectionId;
float m_previousBlendFactor = DefaultBlendFactor;
};
@@ -27,7 +27,7 @@ namespace Multiplayer
uint64_t m_serverConnectionCount = 0;
uint64_t m_recordMetricIndex = 0;
AZ::TimeMs m_totalHistoryTimeMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_totalHistoryTimeMs = AZ::Time::ZeroTimeMs;
static const uint32_t RingbufferSamples = 32;
using MetricRingbuffer = AZStd::array<uint64_t, RingbufferSamples>;
@@ -201,9 +201,9 @@ namespace Multiplayer
AZStd::unique_ptr<IReplicationWindow> m_replicationWindow;
AZStd::unique_ptr<IEntityDomain> m_remoteEntityDomain;
AZ::TimeMs m_entityActivationTimeSliceMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_entityPendingRemovalMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_frameTimeMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_entityActivationTimeSliceMs = AZ::Time::ZeroTimeMs;
AZ::TimeMs m_entityPendingRemovalMs = AZ::Time::ZeroTimeMs;
AZ::TimeMs m_frameTimeMs = AZ::Time::ZeroTimeMs;
HostId m_remoteHostId = InvalidHostId;
uint32_t m_maxRemoteEntitiesPendingCreationCount = AZStd::numeric_limits<uint32_t>::max();
uint32_t m_maxPayloadSize = 0;
@@ -75,7 +75,7 @@ namespace Multiplayer
MultiplayerComponentInputVector m_componentInputs;
ClientInputId m_inputId = ClientInputId{ 0 };
HostFrameId m_hostFrameId = InvalidHostFrameId;
AZ::TimeMs m_hostTimeMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_hostTimeMs = AZ::Time::ZeroTimeMs;
float m_hostBlendFactor = 0.f;
ConstNetworkEntityHandle m_owner;
bool m_wasAttached = false;
@@ -66,11 +66,6 @@ namespace Multiplayer
}
}
inline double ConvertTimeMsToSeconds(AZ::TimeMs value)
{
return static_cast<double>(static_cast<AZ::TimeMs>(value)) / 1000.0;
}
void LocalPredictionPlayerInputComponent::LocalPredictionPlayerInputComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
@@ -162,7 +157,7 @@ namespace Multiplayer
}
const AZ::TimeMs currentTimeMs = AZ::GetElapsedTimeMs();
const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs);
const double clientInputRateSec = AZ::TimeMsToSecondsDouble(cl_InputRateMs);
m_lastInputReceivedTimeMs = currentTimeMs;
// Keep track of last inputs received, also allows us to update frame ids
@@ -267,7 +262,7 @@ namespace Multiplayer
return;
}
const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs);
const double clientInputRateSec = AZ::TimeMsToSecondsDouble(cl_InputRateMs);
// Copy array so we can modify input ids
NetworkInputMigrationVector inputArrayCopy = inputArray;
@@ -342,7 +337,7 @@ namespace Multiplayer
// If this correction is for a move outside our input history window, just start replaying from the oldest move we have available
const uint32_t startReplayIndex = (inputHistorySize > historicalDelta) ? (inputHistorySize - historicalDelta) : 0;
const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs);
const double clientInputRateSec = AZ::TimeMsToSecondsDouble(cl_InputRateMs);
for (uint32_t replayIndex = startReplayIndex; replayIndex < inputHistorySize; ++replayIndex)
{
// Reprocess the input for this frame
@@ -423,9 +418,9 @@ namespace Multiplayer
void LocalPredictionPlayerInputComponentController::UpdateAutonomous(AZ::TimeMs deltaTimeMs)
{
const double deltaTime = ConvertTimeMsToSeconds(deltaTimeMs);
const double clientInputRateSec = ConvertTimeMsToSeconds(cl_InputRateMs);
const double maxRewindHistory = ConvertTimeMsToSeconds(cl_MaxRewindHistoryMs);
const double deltaTime = AZ::TimeMsToSecondsDouble(deltaTimeMs);
const double clientInputRateSec = AZ::TimeMsToSecondsDouble(cl_InputRateMs);
const double maxRewindHistory = AZ::TimeMsToSecondsDouble(cl_MaxRewindHistoryMs);
#ifndef AZ_RELEASE_BUILD
m_moveAccumulator += deltaTime * cl_DebugHackTimeMultiplier;
@@ -13,7 +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");
AZ_CVAR(AZ::TimeMs, cl_DefaultNetworkEntityActivationTimeSliceMs, AZ::Time::ZeroTimeMs, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Max Ms to use to activate entities coming from the network, 0 means instantiate everything");
ClientToServerConnectionData::ClientToServerConnectionData
(
@@ -27,7 +27,7 @@ namespace Multiplayer
CollectHierarchyRoots();
AZ::EntitySystemBus::Handler::BusConnect();
m_updateDebugOverlay.Enqueue(AZ::TimeMs{ 0 }, true);
m_updateDebugOverlay.Enqueue(AZ::Time::ZeroTimeMs, true);
}
MultiplayerDebugHierarchyReporter::~MultiplayerDebugHierarchyReporter()
@@ -127,7 +127,7 @@ namespace Multiplayer
MultiplayerDebugPerEntityReporter::MultiplayerDebugPerEntityReporter()
: m_updateDebugOverlay([this]() { UpdateDebugOverlay(); }, AZ::Name("UpdateDebugPerEntityOverlay"))
{
m_updateDebugOverlay.Enqueue(AZ::TimeMs{ 0 }, true);
m_updateDebugOverlay.Enqueue(AZ::Time::ZeroTimeMs, true);
m_eventHandlers.m_entitySerializeStart = decltype(m_eventHandlers.m_entitySerializeStart)([this](AzNetworking::SerializerMode mode, AZ::EntityId entityId, const char* entityName)
{
@@ -35,7 +35,7 @@ namespace Multiplayer
{
m_networkEditorInterface = AZ::Interface<INetworking>::Get()->CreateNetworkInterface(
AZ::Name(MpEditorInterfaceName), ProtocolType::Tcp, TrustZone::ExternalClientToServer, *this);
m_networkEditorInterface->SetTimeoutMs(AZ::TimeMs{ 0 }); // Disable timeouts on this network interface
m_networkEditorInterface->SetTimeoutMs(AZ::Time::ZeroTimeMs); // Disable timeouts on this network interface
// Wait to activate the editor-server until LegacySystemInterfaceCreated so that the logging system is ready
// Automated testing listens for these logs
+17 -11
View File
@@ -6,10 +6,9 @@
*
*/
#include <MultiplayerToolsSystemComponent.h>
#include <AzNetworking/Framework/NetworkingSystemComponent.h>
#include <Multiplayer/Components/NetBindComponent.h>
#include <Multiplayer/Components/NetworkHierarchyChildComponent.h>
#include <Multiplayer/Components/NetworkHierarchyRootComponent.h>
#include <Source/MultiplayerGem.h>
#include <Source/MultiplayerSystemComponent.h>
#include <Source/AutoGen/AutoComponentTypes.h>
@@ -20,25 +19,32 @@ namespace Multiplayer
MultiplayerModule::MultiplayerModule()
: AZ::Module()
{
m_descriptors.insert(m_descriptors.end(), {
AzNetworking::NetworkingSystemComponent::CreateDescriptor(),
MultiplayerSystemComponent::CreateDescriptor(),
NetBindComponent::CreateDescriptor(),
NetworkSpawnableHolderComponent::CreateDescriptor(),
});
m_descriptors.insert(
m_descriptors.end(),
{
AzNetworking::NetworkingSystemComponent::CreateDescriptor(),
MultiplayerSystemComponent::CreateDescriptor(),
NetBindComponent::CreateDescriptor(),
NetworkSpawnableHolderComponent::CreateDescriptor(),
#ifdef MULTIPLAYER_EDITOR
MultiplayerToolsSystemComponent::CreateDescriptor(),
#endif
});
CreateComponentDescriptors(m_descriptors);
}
AZ::ComponentTypeList MultiplayerModule::GetRequiredSystemComponents() const
{
return AZ::ComponentTypeList
{
return AZ::ComponentTypeList{
azrtti_typeid<AzNetworking::NetworkingSystemComponent>(),
azrtti_typeid<MultiplayerSystemComponent>(),
#ifdef MULTIPLAYER_EDITOR
azrtti_typeid<MultiplayerToolsSystemComponent>(),
#endif
};
}
}
} // namespace Multiplayer
#if !defined(MULTIPLAYER_EDITOR)
AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer, Multiplayer::MultiplayerModule);
@@ -176,7 +176,7 @@ namespace Multiplayer
AZStd::queue<AZStd::string> m_pendingConnectionTickets;
AZStd::unordered_map<uint64_t, NetEntityId> m_playerRejoinData;
AZ::TimeMs m_lastReplicatedHostTimeMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_lastReplicatedHostTimeMs = AZ::Time::ZeroTimeMs;
HostFrameId m_lastReplicatedHostFrameId = HostFrameId(0);
uint64_t m_temporaryUserIdentifier = 0; // Used in the event of a migration or rejoin
@@ -6,7 +6,7 @@
*
*/
#include <MultiplayerToolsModule.h>
#include <MultiplayerToolsSystemComponent.h>
#include <Pipeline/NetworkPrefabProcessor.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
@@ -39,22 +39,4 @@ namespace Multiplayer
{
m_didProcessNetPrefabs = didProcessNetPrefabs;
}
MultiplayerToolsModule::MultiplayerToolsModule()
: AZ::Module()
{
m_descriptors.insert(m_descriptors.end(), {
MultiplayerToolsSystemComponent::CreateDescriptor(),
});
}
AZ::ComponentTypeList MultiplayerToolsModule::GetRequiredSystemComponents() const
{
return AZ::ComponentTypeList
{
azrtti_typeid<MultiplayerToolsSystemComponent>(),
};
}
} // namespace Multiplayer
AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Tools, Multiplayer::MultiplayerToolsModule);
@@ -37,19 +37,5 @@ namespace Multiplayer
bool m_didProcessNetPrefabs = false;
};
class MultiplayerToolsModule
: public AZ::Module
{
public:
AZ_RTTI(MultiplayerToolsModule, "{3F726172-21FC-48FA-8CFA-7D87EBA07E55}", AZ::Module);
AZ_CLASS_ALLOCATOR(MultiplayerToolsModule, AZ::SystemAllocator, 0);
MultiplayerToolsModule();
~MultiplayerToolsModule() override = default;
AZ::ComponentTypeList GetRequiredSystemComponents() const override;
};
} // namespace Multiplayer
@@ -54,10 +54,10 @@ namespace Multiplayer
m_maxPayloadSize = connection.GetConnectionMtu() - UdpPacketHeaderSerializeSize - ReplicationManagerPacketOverhead;
// Schedule ClearRemovedReplicators()
m_clearRemovedReplicators.Enqueue(AZ::TimeMs{ 0 }, true);
m_clearRemovedReplicators.Enqueue(AZ::Time::ZeroTimeMs, true);
// Start window update events
m_updateWindow.Enqueue(AZ::TimeMs{ 0 }, true);
m_updateWindow.Enqueue(AZ::Time::ZeroTimeMs, true);
INetworkEntityManager* networkEntityManager = GetNetworkEntityManager();
if (networkEntityManager != nullptr)
@@ -97,7 +97,7 @@ namespace Multiplayer
notReadyEntities.push_back(entityId);
}
}
if (m_entityActivationTimeSliceMs > AZ::TimeMs{ 0 } && AZ::GetElapsedTimeMs() > endTimeMs)
if (m_entityActivationTimeSliceMs > AZ::Time::ZeroTimeMs && AZ::GetElapsedTimeMs() > endTimeMs)
{
// If we go over our timeslice, break out the loop
break;
@@ -344,7 +344,7 @@ namespace Multiplayer
void EntityReplicator::SetPendingRemoval(AZ::TimeMs pendingRemovalTimeMs)
{
AZ_Assert(m_propertyPublisher, "Only valid if we are publishing updates");
if (pendingRemovalTimeMs > AZ::TimeMs{ 0 })
if (pendingRemovalTimeMs > AZ::Time::ZeroTimeMs)
{
if (!IsPendingRemoval())
{
@@ -26,7 +26,7 @@ namespace Multiplayer
bool PropertySubscriber::IsDeleting() const
{
return m_markForRemovalTimeMs > AZ::TimeMs{ 0 };
return m_markForRemovalTimeMs > AZ::Time::ZeroTimeMs;
}
bool PropertySubscriber::IsDeleted() const
@@ -40,6 +40,6 @@ namespace Multiplayer
// The last packet to have been received about this entity
AzNetworking::PacketId m_lastReceivedPacketId = AzNetworking::InvalidPacketId;
AZ::TimeMs m_markForRemovalTimeMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_markForRemovalTimeMs = AZ::Time::ZeroTimeMs;
};
}
@@ -123,7 +123,7 @@ namespace Multiplayer
AZ_Assert(entityHandle.GetNetBindComponent(), "No NetBindComponent found on networked entity");
}
m_removeList.push_back(entityHandle.GetNetEntityId());
m_removeEntitiesEvent.Enqueue(AZ::TimeMs{ 0 });
m_removeEntitiesEvent.Enqueue(AZ::Time::ZeroTimeMs);
}
}
@@ -44,7 +44,7 @@ namespace Multiplayer
HostFrameId m_hostFrameId = HostFrameId{ 0 };
HostFrameId m_unalteredFrameId = HostFrameId{ 0 };
AZ::TimeMs m_hostTimeMs = AZ::TimeMs{ 0 };
AZ::TimeMs m_hostTimeMs = AZ::Time::ZeroTimeMs;
float m_hostBlendFactor = DefaultBlendFactor;
AzNetworking::ConnectionId m_rewindingConnectionId = AzNetworking::InvalidConnectionId;
};
@@ -53,7 +53,7 @@ namespace Multiplayer
;
serializeContext->Class<NetworkPrefabProcessor, PrefabProcessor>()
->Version(3)
->Version(4)
->Field("SerializationFormat", &NetworkPrefabProcessor::m_serializationFormat)
;
}
@@ -146,6 +146,8 @@ namespace Multiplayer
networkSpawnableAsset.Create(networkSpawnable->GetId());
networkSpawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad);
AZStd::unordered_set<AZ::EntityId> prefabNetEntityIds;
for (auto* prefabEntity : prefabNetEntities)
{
Instance* instance = netEntityToInstanceMap[prefabEntity];
@@ -158,6 +160,22 @@ namespace Multiplayer
netEntity->InvalidateDependencies();
netEntity->EvaluateDependencies();
auto* transformComponent = netEntity->FindComponent<AzFramework::TransformComponent>();
if (transformComponent)
{
AZ::EntityId parentId = transformComponent->GetParentId();
if (parentId.IsValid() && !prefabNetEntityIds.contains(parentId))
{
// Clear parent ID for net entities parented to a non-net entity.
// To be addressed by the spawnable aliases system where non-net entities
// will be spawned together with the networked ones in which case we'll keep
// the cross-spawnable references.
transformComponent->SetParent(AZ::EntityId());
}
}
prefabNetEntityIds.insert(netEntity->GetId());
// Insert the entity into the target net spawnable
netSpawnableEntities.emplace_back(netEntity);
}
@@ -14,6 +14,7 @@
#include <AzCore/Console/Console.h>
#include <AzCore/Name/Name.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/UnitTest/Mocks/MockITime.h>
#include <AzFramework/Components/TransformComponent.h>
#include <benchmark/benchmark.h>
#include <Multiplayer/Components/NetBindComponent.h>
@@ -41,7 +42,6 @@ namespace Multiplayer
AZ::SerializeContext* GetSerializeContext() override { return {}; }
AZ::BehaviorContext* GetBehaviorContext() override { return {}; }
AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return {}; }
const char* GetAppRoot() const override { return {}; }
const char* GetEngineRoot() const override { return {}; }
const char* GetExecutableFolder() const override { return {}; }
void QueryApplicationType([[maybe_unused]] AZ::ApplicationTypeQuery& appType) const override {}
@@ -93,20 +93,6 @@ namespace Multiplayer
}
};
class BenchmarkTime : public AZ::ITime
{
public:
AZ::TimeMs GetElapsedTimeMs() const override
{
return {};
}
AZ::TimeUs GetElapsedTimeUs() const override
{
return {};
}
};
class BenchmarkNetworkTime : public Multiplayer::INetworkTime
{
public:
@@ -350,8 +336,7 @@ namespace Multiplayer
// Without Multiplayer::RegisterMultiplayerComponents() the stats go to invalid id, which is fine for unit tests
GetMultiplayer()->GetStats().ReserveComponentStats(Multiplayer::InvalidNetComponentId, 50, 0);
m_Time = AZStd::make_unique<BenchmarkTime>();
AZ::Interface<AZ::ITime>::Register(m_Time.get());
m_Time = AZStd::make_unique<AZ::StubTimeSystem>();
m_NetworkTime = AZStd::make_unique<BenchmarkNetworkTime>();
AZ::Interface<INetworkTime>::Register(m_NetworkTime.get());
@@ -382,7 +367,6 @@ namespace Multiplayer
m_ConnectionListener.reset();
AZ::Interface<INetworkTime>::Unregister(m_NetworkTime.get());
AZ::Interface<AZ::ITime>::Unregister(m_Time.get());
AZ::Interface<IMultiplayer>::Unregister(m_Multiplayer.get());
AZ::Interface<AZ::ComponentApplicationRequests>::Unregister(m_ComponentApplicationRequests.get());
@@ -415,7 +399,7 @@ namespace Multiplayer
AZStd::unique_ptr<BenchmarkMultiplayer> m_Multiplayer;
AZStd::unique_ptr<BenchmarkNetworkEntityManager> m_NetworkEntityManager;
AZStd::unique_ptr<BenchmarkTime> m_Time;
AZStd::unique_ptr<AZ::StubTimeSystem> m_Time;
AZStd::unique_ptr<BenchmarkNetworkTime> m_NetworkTime;
AZStd::unique_ptr<BenchmarkMultiplayerConnection> m_Connection;
@@ -18,6 +18,7 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/UnitTest/UnitTest.h>
#include <AzCore/UnitTest/Mocks/MockITime.h>
#include <AzFramework/Components/TransformComponent.h>
#include <AzNetworking/Serialization/NetworkInputSerializer.h>
#include <AzNetworking/Serialization/NetworkOutputSerializer.h>
@@ -117,8 +118,7 @@ namespace Multiplayer
ON_CALL(*m_mockNetworkEntityManager, GetEntity(_)).WillByDefault(Invoke(this, &HierarchyTests::GetEntity));
ON_CALL(*m_mockNetworkEntityManager, GetNetEntityIdById(_)).WillByDefault(Invoke(this, &HierarchyTests::GetNetEntityIdById));
m_mockTime = AZStd::make_unique<NiceMock<MockTime>>();
AZ::Interface<AZ::ITime>::Register(m_mockTime.get());
m_mockTime = AZStd::make_unique<AZ::NiceTimeSystemMock>();
m_eventScheduler = AZStd::make_unique<AZ::EventSchedulerSystemComponent>();
@@ -168,7 +168,6 @@ namespace Multiplayer
m_networkEntityAuthorityTracker.reset();
AZ::Interface<INetworkTime>::Unregister(m_mockNetworkTime.get());
AZ::Interface<AZ::ITime>::Unregister(m_mockTime.get());
AZ::Interface<INetworkEntityManager>::Unregister(m_mockNetworkEntityManager.get());
AZ::Interface<IMultiplayer>::Unregister(m_mockMultiplayer.get());
AZ::Interface<AZ::ComponentApplicationRequests>::Unregister(m_mockComponentApplicationRequests.get());
@@ -207,8 +206,8 @@ namespace Multiplayer
AZStd::unique_ptr<NiceMock<MockMultiplayer>> m_mockMultiplayer;
AZStd::unique_ptr<MockNetworkEntityManager> m_mockNetworkEntityManager;
AZStd::unique_ptr<NiceMock<MockTime>> m_mockTime;
AZStd::unique_ptr<AZ::EventSchedulerSystemComponent> m_eventScheduler;
AZStd::unique_ptr<AZ::NiceTimeSystemMock> m_mockTime;
AZStd::unique_ptr<NiceMock<MockNetworkTime>> m_mockNetworkTime;
AZStd::unique_ptr<NiceMock<IMultiplayerConnectionMock>> m_mockConnection;
@@ -103,13 +103,6 @@ namespace UnitTest
MOCK_METHOD3(OnDisconnect, void(IConnection*, DisconnectReason, TerminationEndpoint));
};
class MockTime : public AZ::ITime
{
public:
MOCK_CONST_METHOD0(GetElapsedTimeUs, AZ::TimeUs());
MOCK_CONST_METHOD0(GetElapsedTimeMs, AZ::TimeMs());
};
class MockNetworkTime : public Multiplayer::INetworkTime
{
public:
@@ -149,7 +142,6 @@ namespace UnitTest
MOCK_METHOD0(GetSerializeContext, AZ::SerializeContext* ());
MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ());
MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ());
MOCK_CONST_METHOD0(GetAppRoot, const char* ());
MOCK_CONST_METHOD0(GetEngineRoot, const char* ());
MOCK_CONST_METHOD0(GetExecutableFolder, const char* ());
MOCK_METHOD0(GetDrillerManager, AZ::Debug::DrillerManager* ());
@@ -12,7 +12,7 @@
#include <Multiplayer/NetworkTime/RewindableObject.h>
#include <Source/NetworkTime/NetworkTime.h>
#include <AzCore/Console/LoggerSystemComponent.h>
#include <AzCore/Time/TimeSystemComponent.h>
#include <AzCore/Time/TimeSystem.h>
#include <AzCore/UnitTest/TestTypes.h>
namespace UnitTest
@@ -23,7 +23,7 @@ namespace UnitTest
public:
Multiplayer::NetworkTime m_networkTime;
AZ::LoggerSystemComponent m_loggerComponent;
AZ::TimeSystemComponent m_timeComponent;
AZ::TimeSystem m_timeSystem;
};
static constexpr uint32_t RewindableContainerSize = 7;
@@ -43,7 +43,7 @@ namespace UnitTest
// Test rewind for all pushed values and overall size
for (uint32_t idx = 0; idx < RewindableContainerSize; ++idx)
{
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(idx), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(idx), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(idx + 1, test.size());
EXPECT_EQ(idx, test.back());
}
@@ -70,9 +70,9 @@ namespace UnitTest
EXPECT_TRUE(test.empty());
// Test rewind for pop_back and clear
Multiplayer::ScopedAlterTime pop_time(static_cast<Multiplayer::HostFrameId>(RewindableContainerSize), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime pop_time(static_cast<Multiplayer::HostFrameId>(RewindableContainerSize), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(RewindableContainerSize - 1, test.size());
Multiplayer::ScopedAlterTime clear_time(static_cast<Multiplayer::HostFrameId>(RewindableContainerSize + 1), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime clear_time(static_cast<Multiplayer::HostFrameId>(RewindableContainerSize + 1), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(0, test.size());
// Test copy_values and resize_no_construct
@@ -100,7 +100,7 @@ namespace UnitTest
// Test rewind for all values and overall size
for (uint32_t idx = 1; idx <= RewindableContainerSize; ++idx)
{
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(idx), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(idx), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
for (uint32_t testIdx = 0; testIdx < RewindableContainerSize; ++testIdx)
{
if (testIdx < idx)
@@ -10,7 +10,7 @@
#include <Multiplayer/NetworkTime/RewindableObject.h>
#include <Source/NetworkTime/NetworkTime.h>
#include <AzCore/Console/LoggerSystemComponent.h>
#include <AzCore/Time/TimeSystemComponent.h>
#include <AzCore/Time/TimeSystem.h>
#include <AzCore/UnitTest/TestTypes.h>
namespace UnitTest
@@ -21,7 +21,7 @@ namespace UnitTest
public:
Multiplayer::NetworkTime m_networkTime;
AZ::LoggerSystemComponent m_loggerComponent;
AZ::TimeSystemComponent m_timeComponent;
AZ::TimeSystem m_timeSystem;
};
static constexpr uint32_t RewindableBufferFrames = 32;
@@ -39,7 +39,7 @@ namespace UnitTest
for (uint32_t i = 0; i < 16; ++i)
{
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(i), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(i, test);
}
@@ -52,7 +52,7 @@ namespace UnitTest
for (uint32_t i = 16; i < 48; ++i)
{
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(i), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(i, test);
}
}
@@ -70,15 +70,15 @@ namespace UnitTest
{
// Test that Get/GetPrevious return different value when not on the owning connection
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(RewindableBufferFrames - 1), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(RewindableBufferFrames - 1), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(RewindableBufferFrames - 1, test.Get());
EXPECT_EQ(RewindableBufferFrames - 2, test.GetPrevious());
}
// Test that Get/GetPrevious return the unaltered frame on the owning conection
Multiplayer::GetNetworkTime()->AlterTime(static_cast<Multiplayer::HostFrameId>(RewindableBufferFrames - 1), AZ::TimeMs{ 0 }, 1.f, AzNetworking::ConnectionId(0));
Multiplayer::GetNetworkTime()->AlterTime(static_cast<Multiplayer::HostFrameId>(RewindableBufferFrames - 1), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::ConnectionId(0));
{
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(RewindableBufferFrames - 1), AZ::TimeMs{ 0 }, 1.f, AzNetworking::ConnectionId(0));
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(RewindableBufferFrames - 1), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::ConnectionId(0));
test.SetOwningConnectionId(AzNetworking::ConnectionId(0));
EXPECT_EQ(RewindableBufferFrames - 1, test.Get());
EXPECT_EQ(RewindableBufferFrames - 1, test.GetPrevious());
@@ -99,7 +99,7 @@ namespace UnitTest
{
// Note that we didn't actually set any value for time rewindableBufferFrames, so we're testing fetching a value past the last time set
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(RewindableBufferFrames), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(RewindableBufferFrames), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(RewindableBufferFrames - 1, test);
}
}
@@ -122,7 +122,7 @@ namespace UnitTest
for (uint32_t i = 0; i < RewindableBufferFrames; ++i)
{
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(i), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
const Object& value = test;
EXPECT_EQ(value.value, i);
}
@@ -131,19 +131,19 @@ namespace UnitTest
TEST_F(RewindableObjectTests, TestBackfillOnLargeTimestep)
{
Multiplayer::RewindableObject<uint32_t, RewindableBufferFrames> test(0);
Multiplayer::ScopedAlterTime time1(static_cast<Multiplayer::HostFrameId>(0), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time1(static_cast<Multiplayer::HostFrameId>(0), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
test = 1;
Multiplayer::ScopedAlterTime time2(static_cast<Multiplayer::HostFrameId>(31), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time2(static_cast<Multiplayer::HostFrameId>(31), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
test = 2;
for (uint32_t i = 0; i < 31; ++i)
{
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(i), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(1, test);
}
Multiplayer::ScopedAlterTime time3(static_cast<Multiplayer::HostFrameId>(31), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time3(static_cast<Multiplayer::HostFrameId>(31), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(2, test);
}
@@ -159,7 +159,7 @@ namespace UnitTest
for (uint32_t i = 0; i < 1000; ++i)
{
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(1000 - i), AZ::TimeMs{ 0 }, 1.f, AzNetworking::InvalidConnectionId);
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(1000 - i), AZ::Time::ZeroTimeMs, 1.f, AzNetworking::InvalidConnectionId);
EXPECT_EQ(1000, test);
}
}
@@ -10,6 +10,6 @@ set(FILES
Include/Multiplayer/IMultiplayerTools.h
Source/Pipeline/NetworkPrefabProcessor.cpp
Source/Pipeline/NetworkPrefabProcessor.h
Source/MultiplayerToolsModule.h
Source/MultiplayerToolsModule.cpp
Source/MultiplayerToolsSystemComponent.cpp
Source/MultiplayerToolsSystemComponent.h
)