Integrating up through commit 90f050496

This commit is contained in:
alexpete
2021-04-07 14:03:29 -07:00
parent 8f2ed080a9
commit c2cbd430fe
2694 changed files with 285622 additions and 176874 deletions
@@ -0,0 +1,13 @@
#pragma once
{% set Namespace = dataFiles[0].attrib['Namespace'] %}
namespace {{ Namespace }}
{
enum class ComponentTypes
{
{% for Component in dataFiles %}
{% set ComponentName = Component.attrib['Name'] %}
{{ ComponentName }},
{% endfor %}
};
}
@@ -0,0 +1,306 @@
{% macro UpperFirst(text) %}{{ text[0] | upper}}{{ text[1:] }}{% endmacro %}
{% macro LowerFirst(text) %}{{ text[0] | lower}}{{ text[1:] }}{% endmacro %}
{#
#}
{%- macro ParseRpcParams(property, outNames, outTypes, outDefines, use_default_value=False) -%}
{%- for Param in property.iter('Param') -%}
{%- do outNames.append(Param.attrib['Name']) -%}
{%- do outTypes.append(Param.attrib['Type']) -%}
{%- if use_default_value and Param.attrib['DefaultValue'] -%}
{%- do outDefines.append('const ' ~ Param.attrib['Type'] ~ '& ' + Param.attrib['Name'] + ' = ' + Param.attrib['DefaultValue']) -%}
{%- else -%}
{%- do outDefines.append('const ' ~ Param.attrib['Type'] ~ '& ' ~ Param.attrib['Name']) -%}
{%- endif -%}
{%- endfor -%}
{%- endmacro -%}
{#
#}
{%- macro ParseIncludes(Component) -%}
{%- for Include in Component.iter('Include') -%}
{{ caller(Include) -}}
{%- endfor -%}
{%- endmacro -%}
{#
#}
{%- macro ParseNetworkInputs(Component) -%}
{%- for NetworkInput in Component.iter('NetworkInput') -%}
{{ caller(NetworkInput) -}}
{%- endfor -%}
{%- endmacro -%}
{#
#}
{%- macro ParseArchetypeProperties(Component) -%}
{%- for ArchetypeProperty in Component.iter('ArchetypeProperty') -%}
{{ caller(ArchetypeProperty) -}}
{%- endfor -%}
{%- endmacro -%}
{#
#}
{%- macro ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) -%}
{%- for NetworkProperty in Component.iter('NetworkProperty') -%}
{%- if NetworkProperty.attrib['ReplicateFrom'] == ReplicateFrom and NetworkProperty.attrib['ReplicateTo'] == ReplicateTo -%}
{{ caller(NetworkProperty) -}}
{%- endif -%}
{%- endfor -%}
{%- endmacro -%}
{#
#}
{%- macro ParseRemoteProcedures(Component, InvokeFrom, HandleOn) -%}
{%- for RemoteProcedure in Component.iter('RemoteProcedure') -%}
{%- if RemoteProcedure.attrib['InvokeFrom'] == InvokeFrom and RemoteProcedure.attrib['HandleOn'] == HandleOn -%}
{{ caller(RemoteProcedure) -}}
{%- endif -%}
{%- endfor -%}
{%- endmacro -%}
{#
#}
{%- macro GetNetPropertiesClassName(Component, ClassType) -%}
{{ Component.attrib['Name'] }}{{ ClassType }}NetProperties
{%- endmacro -%}
{#
#}
{%- macro GetNetPropertiesDirtyEnumName(Component, ClassType, ReplicateFrom, ReplicateTo) -%}
{{ ReplicateFrom }}To{{ ReplicateTo }}DirtyEnum
{%- endmacro -%}
{#
#}
{%- macro GetNetPropertiesPropertyDirtyEnum(Property) -%}
{{ Property.attrib['Name'] }}_DirtyFlag
{%- endmacro -%}
{#
#}
{%- macro GetNetPropertiesQualifiedPropertyDirtyEnum(Component, ClassType, ReplicateFrom, ReplicateTo, Property) -%}
{{ GetNetPropertiesDirtyEnumName(Component, ClassType, ReplicateFrom, ReplicateTo) }}::{{ GetNetPropertiesPropertyDirtyEnum(Property) }}
{%- endmacro -%}
{#
#}
{%- macro GetModelClassName(Component, ClassType) -%}
{{ Component.attrib['Name'] }}Model{{ ClassType }}
{%- endmacro -%}
{#
#}
{%- macro GetArchetypeClassName(Entity, ClassType) -%}
{{ Entity.attrib['Name'] }}Archetype{{ ClassType }}
{%- endmacro -%}
{#
#}
{%- macro GetNetPropertiesSetName(ReplicateFrom, ReplicateTo) -%}
{{ ReplicateFrom }}To{{ ReplicateTo }}
{%- endmacro -%}
{#
#}
{%- macro GetModelReplicationRecordName(Component, ClassType) -%}
{{ Component.attrib['Name'] }}{{ ClassType }}ReplicationRecord
{%- endmacro -%}
{#
#}
{%- macro GetComponentDeltaName(Component, ClassType) -%}
{{ Component.attrib['Name'] }}Delta{{ ClassType }}
{%- endmacro -%}
{#
#}
{%- macro GetNetworkPropertyEventType(Property) -%}
AZ::Event<{{ Property.attrib['Type'] }}>
{%- endmacro -%}
{#
#}
{%- macro GetEntityClassName(Entity, ClassType) -%}
{{ Entity.attrib['Name'] }}{{ ClassType }}
{%- endmacro -%}
{#
#}
{%- macro GetEntityReplicatorName(Entity, ClassType) -%}
{{ Entity.attrib['Name'] }}{{ ClassType }}Replicator
{%- endmacro -%}
{#
#}
{%- macro GetEntityReplicationRecordName(Entity) -%}
{{ Entity.attrib['Name'] }}ReplicationRecord
{%- endmacro -%}
{#
#}
{% macro DefineNetworkPropertyReflection(Component, ReplicateFrom, ReplicateTo, ClassName) %}
{% call(Property) ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
{% if Property.attrib['ExposeToEditor'] | booleanTrue %}
->Field("{{ Property.attrib['Name'] }}", &{{ ClassName }}::m_{{ LowerFirst(Property.attrib['Name']) }})
{% endif %}
{% endcall -%}
{% endmacro %}
{#
#}
{% macro DefineArchetypePropertyReflection(Component, ClassName) %}
{% call(Property) ParseArchetypeProperties(Component) %}
{% if Property.attrib['ExposeToEditor'] | booleanTrue %}
->Field("{{ Property.attrib['Name'] }}", &{{ ClassName }}::m_{{ LowerFirst(Property.attrib['Name']) }})
{% endif %}
{% endcall %}
{% endmacro %}
{#
#}
{% macro DefineNetworkPropertyConstructors(Component, ReplicateFrom, ReplicateTo, ClassType) %}
{% call(Property) ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
{% if Property.attrib['Container'] == 'Array' %}
, m_{{ LowerFirst(Property.attrib['Name']) }}({% if Property.attrib['IsRewindable']|booleanTrue %}Multiplayer::RewindableObject<{{ Property.attrib['Type'] }}, Multiplayer::RewindHistorySize>({% endif %}{{ Property.attrib['Init'] }}{% if Property.attrib['IsRewindable']|booleanTrue %}, this){% endif %})
{% elif Property.attrib['Container'] == 'Vector' %}
, m_{{ LowerFirst(Property.attrib['Name']) }}({{ Property.attrib['Init'] }})
{% elif Property.attrib['IsRewindable']|booleanTrue %}
, m_{{ LowerFirst(Property.attrib['Name']) }}({{ Property.attrib['Init'] }}, this)
{% else %}
, m_{{ LowerFirst(Property.attrib['Name']) }}({{ Property.attrib['Init'] }})
{% endif %}
{% endcall %}
{% endmacro %}
{#
#}
{% macro DefineArchetypePropertyConstructors(Component) %}
{% call(Property) ParseArchetypeProperties(Component) %}
{% if Property.attrib['Container'] == 'Vector' %}
, m_{{ LowerFirst(Property.attrib['Name']) }}({{ Property.attrib['Init'] }}, {{ Property.attrib['Count'] }})
{% else %}
, m_{{ LowerFirst(Property.attrib['Name']) }}({{ Property.attrib['Init'] }})
{% endif %}
{% endcall %}
{% endmacro %}
{#
#}
{% macro ParseComponentServiceTypeAndName(Component) %}
{% for Service in Component.iter('ComponentRelation') %}
{% if Service.attrib['Constraint'] != 'Incompatible' %}
{% set Type = Service.attrib['Namespace'] + "::" + Service.attrib['Name'] %}
{% set Name = 'm_' + LowerFirst(Service.attrib['Name']) %}
{{ caller(Type, Name) -}}
{% endif %}
{% endfor %}
{% endmacro %}
{#
#}
{%- macro GetRpcEventAccessorName(InvokeFrom, HandleOn) -%}
{{ "GetRpc" + InvokeFrom + "To" + HandleOn + "Event" }}
{% endmacro %}
{#
#}
{% macro DeclareRpcHandler(Property, HandleOn, IsOverride) %}
{% set paramNames = [] %}
{% set paramTypes = [] %}
{% set paramDefines = [] %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
{{ ParseRpcParams(Property, paramNames, paramTypes, paramDefines) }}
{% if IsOverride %}
void Handle{{ PropertyName }}({{ ', '.join(paramDefines) }}) override {}
{% else %}
//! {{ PropertyName }} Handler
//! {{ Property.attrib['Description'] }}
//! HandleOn {{ HandleOn }}
virtual void Handle{{ PropertyName }}({{ ', '.join(paramDefines) }}) = 0;
{% endif %}
{% endmacro %}
{#
#}
{% macro DeclareRpcHandlers(Component, InvokeFrom, HandleOn, IsOverride) %}
{% call(Property) ParseRemoteProcedures(Component, InvokeFrom, HandleOn) %}
{{- DeclareRpcHandler(Property, HandleOn, IsOverride) -}}
{% endcall %}
{% endmacro %}
{#
#}
{%- macro EmitDerivedClassesComment(dataFileNames, Component, ComponentName, ComponentNameBase, ComponentDerived, ControllerName, ControllerNameBase, ControllerDerived, NetworkInputCount) -%}
{% if ComponentDerived or ControllerDerived %}
/*
/// You may use the classes below as a basis for your new derived classes. Derived classes must be marked in {{ (dataFileNames[0] | basename) }}
/// Place in your .h
#pragma once
#include <Source/AutoGen/{{ ComponentName }}.AutoComponent.h>
namespace {{ Component.attrib['Namespace'] }}
{
{% if ComponentDerived %}
class {{ ComponentName }}
: public {{ ComponentNameBase }}
{
public:
AZ_MULTIPLAYER_COMPONENT({{ Component.attrib['Namespace'] }}::{{ ComponentName }}, s_{{ LowerFirst(ComponentName) }}ConcreteUuid, {{ Component.attrib['Namespace'] }}::{{ ComponentNameBase }});
static void Reflect([[maybe_unused]] AZ::ReflectContext* context);
void OnInit() override {}
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
{{ DeclareRpcHandlers(Component, 'Authority', 'Client', true)|indent(8) }}
};
{% endif %}
{% if ControllerDerived %}
class {{ ControllerName }}
: public {{ ControllerNameBase }}
{
public:
{{ ControllerName }}({{ ComponentName }}& parent) : {{ ControllerNameBase }}(parent) {}
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
{% if NetworkInputCount > 0 %}
//! Common input processing logic for the NetworkInput.
//! @param input input structure to process
//! @param deltaTime amount of time to integrate the provided inputs over
void ProcessInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) override {}
{%endif %}
{{ DeclareRpcHandlers(Component, 'Server', 'Authority', true)|indent(8) }}
{{ DeclareRpcHandlers(Component, 'Client', 'Authority', true)|indent(8) }}
{{ DeclareRpcHandlers(Component, 'Autonomous', 'Authority', true)|indent(8) }}
{{ DeclareRpcHandlers(Component, 'Authority', 'Autonomous', true)|indent(8) }}
};
{% endif %}
}
{% if ComponentDerived %}
/// Place in your .cpp
namespace {{ Component.attrib['Namespace'] }}
{
void {{ ComponentName }}::{{ ComponentName }}::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<{{ ComponentName }}, {{ ComponentNameBase }}>()
->Version(1);
}
}
}
{% endif %}
*/
{% else %}
// NOTE:
// No component roles have been overridden. You can modify {{ (dataFileNames[0] | basename) }} to specify derived classes for your desired network role.
// Once your modifications are complete, build the game.
// Your build will fail, but this comment will be replaced with a stub that can be used as the basis for your derived component roles.
{% endif %}
{%- endmacro -%}
@@ -0,0 +1,479 @@
{% import 'AutoComponent_Common.jinja' as AutoComponentMacros %}
{% macro UpperFirst(text) %}{{ text[0] | upper}}{{ text[1:] }}{% endmacro %}
{% macro LowerFirst(text) %}{{ text[0] | lower}}{{ text[1:] }}{% endmacro %}
{#
#}
{% macro DeclareNetworkPropertyGetter(Property) %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
{% if Property.attrib['Container'] == 'Array' %}
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
void {{ PropertyName }}AddEvent(AZ::Event<int32_t, {{ Property.attrib['Type'] }}>::Handler& handler);
{% endif %}
const AZStd::array<{% if Property.attrib['IsRewindable']|booleanTrue %}Multiplayer::RewindableObject<{% endif %}{{ Property.attrib['Type'] }}{% if Property.attrib['IsRewindable']|booleanTrue %}, Multiplayer::k_RewindHistorySize>{% endif %}, {{ Property.attrib['Count'] }}> &Get{{ PropertyName }}Array() const;
const {{ Property.attrib['Type'] }} &Get{{ PropertyName }}(int32_t index) const;
{% elif Property.attrib['Container'] == 'Vector' %}
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
void {{ PropertyName }}AddEvent(AZ::Event<int32_t, {{ Property.attrib['Type'] }}>::Handler& handler);
void {{ PropertyName }}SizeChangedAddEvent(AZ::Event<uint32_t>::Handler& handler);
{% endif %}
const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> &Get{{ PropertyName }}Vector() const;
const {{ Property.attrib['Type'] }} &Get{{ PropertyName }}(int32_t index) const;
const {{ Property.attrib['Type'] }} &{{ PropertyName }}GetBack() const;
uint32_t {{ PropertyName }}GetSize() const;
{% else %}
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
void {{ PropertyName }}AddEvent(AZ::Event<{{ Property.attrib['Type'] }}>::Handler& handler);
{% endif %}
const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const;
{% endif %}
{% endmacro %}
{#
#}
{% macro DeclareNetworkPropertySetter(Property) %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
{% if Property.attrib['IsPredictable'] | booleanTrue %}
{% if Property.attrib['Container'] == 'Array' %}
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value);
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index);
{% elif Property.attrib['Container'] == 'Vector' %}
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index, const {{ Property.attrib['Type'] }}& value);
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&, int32_t index);
bool {{ PropertyName }}PushBack(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value);
bool {{ PropertyName }}PopBack(const Multiplayer::NetworkInput&);
void {{ PropertyName }}Clear(const Multiplayer::NetworkInput&);
{% elif Property.attrib['Container'] == 'Object' %}
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value);
{{ Property.attrib['Type'] }}& Modify{{ PropertyName }}(const Multiplayer::NetworkInput&);
{% else %}
void Set{{ PropertyName }}(const Multiplayer::NetworkInput&, const {{ Property.attrib['Type'] }}& value);
{% endif %}
{% endif %}
{% endmacro %}
{#
#}
{% macro DeclareNetworkPropertyGetters(Component, ReplicateFrom, ReplicateTo, IsProtected) %}
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
{% if Property.attrib['IsPublic'] | booleanTrue != IsProtected %}
//! {{ PropertyName }} Accessors
//! {{ Property.attrib['Description'] }}.
{{ DeclareNetworkPropertyGetter(Property) }}
{% endif %}
{% endcall %}
{% endmacro %}
{#
#}
{% macro DeclareArchetypePropertyGetter(Property) %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
{% if Property.attrib['Container'] == 'Array' %}
const AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Array() const;
const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}(int32_t index) const;
{% elif Property.attrib['Container'] == 'Vector' %}
const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& Get{{ PropertyName }}Vector() const;
const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}(int32_t index) const;
const {{ Property.attrib['Type'] }}& {{ PropertyName }}GetBack() const;
uint32_t {{ PropertyName }}GetSize() const;
const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const;
{% else %}
const {{ Property.attrib['Type'] }}& Get{{ PropertyName }}() const;
{% endif %}
{% endmacro %}
{#
#}
{% macro DeclareArchetypePropertyGetters(Component) %}
{% call(Property) AutoComponentMacros.ParseArchetypeProperties(Component) %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
//! Get{{ PropertyName }}
//! {{ Property.attrib['Description'] }}.
{{ DeclareArchetypePropertyGetter(Property) }}
{% endcall %}
{% endmacro %}
{#
#}
{% macro DeclareNetworkPropertyAccessors(Component, ReplicateFrom, ReplicateTo, IsProtected) %}
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
{% if Property.attrib['IsPublic'] | booleanTrue != IsProtected %}
//! {{ PropertyName }} Accessors
//! {{ Property.attrib['Description'] }}.
{{ DeclareNetworkPropertyGetter(Property) -}}
{{ DeclareNetworkPropertySetter(Property) }}
{% endif %}
{% endcall %}
{% endmacro %}
{#
#}
{% macro DeclareRpcInvocation(Property, HandleOn) %}
{% set paramNames = [] %}
{% set paramTypes = [] %}
{% set paramDefines = [] %}
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
{{ AutoComponentMacros.ParseRpcParams(Property, paramNames, paramTypes, paramDefines, true) }}
//! {{ PropertyName }} Invocation
//! {{ Property.attrib['Description'] }}
//! HandleOn {{ HandleOn }}
void {{ PropertyName }}({{ ', '.join(paramDefines) }});
{% endmacro %}
{#
#}
{% macro DeclareRpcInvocations(Component, Section, HandleOn, ProctectedSection) %}
{% call(Property) AutoComponentMacros.ParseRemoteProcedures(Component, Section, HandleOn) %}
{% if Property.attrib['IsPublic']|booleanTrue == ProctectedSection %}
{{- DeclareRpcInvocation(Property, HandleOn) -}}
{% endif %}
{% endcall %}
{% endmacro %}
{#
#}
{% macro DeclareNetworkPropertyEvents(Component, ReplicateFrom, ReplicateTo) %}
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
{% if Property.attrib['Container'] == 'Array' %}
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
AZ::Event<int32_t, {{ Property.attrib['Type'] }}> m_{{ LowerFirst(Property.attrib['Name']) }}Event;
{% endif %}
{% elif Property.attrib['Container'] == 'Vector' %}
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
AZ::Event<int32_t, {{ Property.attrib['Type'] }}> m_{{ LowerFirst(Property.attrib['Name']) }}Event;
AZ::Event<uint32_t> m_{{ LowerFirst(Property.attrib['Name']) }}SizeChangedEvent;
{% endif %}
{% else %}
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
AZ::Event<{{ Property.attrib['Type'] }}> m_{{ LowerFirst(Property.attrib['Name']) }}Event;
{% endif %}
{% endif %}
{% endcall %}
{% endmacro %}
{#
#}
{% macro DeclareNetworkPropertyVars(Component, ReplicateFrom, ReplicateTo) %}
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
{% if Property.attrib['Container'] == 'Array' %}
AZStd::array<{% if Property.attrib['IsRewindable']|booleanTrue %}Multiplayer::RewindableObject<{% endif %}{{ Property.attrib['Type'] }}{% if Property.attrib['IsRewindable']|booleanTrue %}, Multiplayer::RewindHistorySize>{% endif %}, {{ Property.attrib['Count'] }}> m_{{ Property.attrib['Name'] }};
{% elif Property.attrib['Container'] == 'Vector' %}
AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> m_{{ LowerFirst(Property.attrib['Name']) }};
{% elif Property.attrib['IsRewindable']|booleanTrue %}
Multiplayer::RewindableObject<{{ Property.attrib['Type'] }}, Multiplayer::RewindHistorySize> m_{{ LowerFirst(Property.attrib['Name']) }} = {{ Property.attrib['Init'] }};
{% else %}
{{ Property.attrib['Type'] }} m_{{ LowerFirst(Property.attrib['Name']) }} = {{ Property.attrib['Init'] }};
{% endif %}
{% endcall %}
{% endmacro %}
{#
#}
{% macro DeclareArchetypePropertyVars(Component) %}
{% call(Property) AutoComponentMacros.ParseArchetypeProperties(Component) %}
{% if Property.attrib['Container'] == 'Array' %}
AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> m_{{ LowerFirst(Property.attrib['Name']) }};
{% elif Property.attrib['Container'] == 'Vector' %}
AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> m_{{ LowerFirst(Property.attrib['Name']) }};
{% else %}
{{ Property.attrib['Type'] }} m_{{ LowerFirst(Property.attrib['Name']) }};
{% endif %}
{% endcall %}
{% endmacro %}
{#
#}
#pragma once
{% for Component in dataFiles %}
{% set ComponentName = Component.attrib['Name'] %}
{% set ComponentBaseName = ComponentName %}
{% set ComponentDerived = Component.attrib['OverrideComponent']|booleanTrue %}
{% set ControllerDerived = Component.attrib['OverrideController']|booleanTrue %}
{% if ComponentDerived %}
{% set ComponentBaseName = ComponentName + "Base" %}
{% endif %}
{% set ControllerName = ComponentName + "Controller" %}
{% set ControllerBaseName = ControllerName %}
{% if ControllerDerived %}
{% set ControllerBaseName = ControllerName + "Base" %}
{% endif %}
{% set NetworkInputCount = Component.findall('NetworkInput') | len %}
{% set NetworkPropertyCount = Component.findall('NetworkProperty') | len %}
{% set RpcCount = Component.findall('RemoteProcedure') | len %}
#include "AutoComponentTypes.h"
#include <AzCore/EBus/Event.h>
#include <AzCore/EBus/ScheduledEvent.h>
#include <AzNetworking/DataStructures/FixedSizeBitsetView.h>
#include <Source/NetworkEntity/NetworkEntityHandle.h>
#include <Source/NetworkEntity/EntityReplication/ReplicationRecord.h>
#include <Source/Components/MultiplayerComponent.h>
#include <Source/Components/MultiplayerController.h>
#include <Source/NetworkInput/IMultiplayerComponentInput.h>
#include <Source/NetworkTime/RewindableObject.h>
#include <Source/MultiplayerTypes.h>
{% call(Include) AutoComponentMacros.ParseIncludes(Component) %}
#include <{{ Include.attrib['File'] }}>
{% endcall %}
{% for Service in Component.iter('ComponentRelation') %}
{% if Service.attrib['Constraint'] != 'Incompatible' %}
namespace {{ Service.attrib['Namespace'] }}
{
class {{ Service.attrib['Name'] }};
{% if Service.attrib['HasController']|booleanTrue %}
class {{ Service.attrib['Name'] }}Controller;
{% endif %}
}
{% endif %}
{% endfor %}
{{ AutoComponentMacros.EmitDerivedClassesComment(dataFileNames, Component, ComponentName, ComponentBaseName, ComponentDerived, ControllerName, ControllerBaseName, ControllerDerived, NetworkInputCount) }}
namespace {{ Component.attrib['Namespace'] }}
{
//! Forward declarations
class {{ ComponentName }};
class {{ ControllerName }};
//! Returns a human readable name for the provided remoteProcedureId.
const char* GetRemoteProcedureName(uint16_t remoteProcedureId);
{% set RecordName = ComponentName + "Record" %}
//! @class {{RecordName }}
//! @brief A record of the changed bits in the NetworkProperties for component {{ ComponentName }}.
class {{ RecordName }}
{
public:
//! AllocateRecord
//! Allocates and returns a new record. Will reserve storage in the provided ReplicationRecord.
static AZStd::unique_ptr<{{ RecordName }}> AllocateRecord(Multiplayer::ReplicationRecord& replicationRecord);
//! CanAttachRecord
//! Returns a true if we can attach a {{ ClassType }}Record to the ReplicationRecord.
static bool CanAttachRecord(Multiplayer::ReplicationRecord& replicationRecord);
//! AttachRecord
//! Returns a {{ ClassType }}Record that has been attached to the ReplicationRecord. This will consume bits in the provided ReplicationRecord.
static {{ RecordName }} AttachRecord(Multiplayer::ReplicationRecord& replicationRecord);
//! SetPredictableBits
//! Sets the bits in the attached record that correspond to predictable network properties.
void SetPredictableBits();
{% set networkPropertyCount = {'value' : 0} %}
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, 'Authority', 'Client') %}
{%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%}
{% endcall %}
{% if networkPropertyCount.value > 0 %}
AzNetworking::FixedSizeBitsetView m_authorityToClient;
{% endif %}
{% set networkPropertyCount = {'value' : 0} %}
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, 'Authority', 'Server') %}
{%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%}
{% endcall %}
{% if networkPropertyCount.value > 0 %}
AzNetworking::FixedSizeBitsetView m_authorityToServer};
{% endif %}
{% set networkPropertyCount = {'value' : 0} %}
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, 'Authority', 'Autonomous') %}
{%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%}
{% endcall %}
{% if networkPropertyCount.value > 0 %}
AzNetworking::FixedSizeBitsetView m_authorityToAutonomous;
{% endif %}
{% set networkPropertyCount = {'value' : 0} %}
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, 'Autonomous', 'Authority') %}
{%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%}
{% endcall %}
{% if networkPropertyCount.value > 0 %}
AzNetworking::FixedSizeBitsetView m_autonomousToAuthority;
{% endif %}
private:
{{ RecordName }}
(
Multiplayer::ReplicationRecord& replicationRecord,
uint32_t authorityToClientSimluationStartOffset,
uint32_t authorityToServerSimluationStartOffset,
uint32_t authorityToAutonomousStartOffset,
uint32_t autonomousToAuthorityStartOffset
);
};
{% if NetworkInputCount > 0 %}
class NetworkInput
: public Multiplayer::IMultiplayerComponentInput
{
public:
static const Multiplayer::NetComponentId s_componentId = static_cast<Multiplayer::NetComponentId>({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }});
Multiplayer::NetComponentId GetComponentId() const override;
INetworkInput& operator=(const INetworkInput& rhs) override;
bool Serialize(AzNetworking::ISerializer& serializer);
{% call(Input) AutoComponentMacros.ParseNetworkInputs(Component) %}
{{ Input.attrib['Type'] }} m_{{ LowerFirst(Input.attrib['Name']) }} = {{ Input.attrib['Type'] }}({{ Input.attrib['Init'] }});
{% endcall %}
};
{% endif %}
class {{ ControllerBaseName }}{% if not ControllerDerived %} final{% endif %}{{ "" }}
: public Multiplayer::MultiplayerController
{
public:
{{ ControllerBaseName }}({{ ComponentName }}& owner);
~{{ ControllerBaseName }}() override = default;
void NetworkAttach(Multiplayer::NetBindComponent* netBindComponent, Multiplayer::ReplicationRecord& predictableEntityRecord);
void Activate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void Deactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override;
const {{ ComponentName }}& GetParent() const;
{{ ComponentName }}& GetParent();
{% if ControllerDerived %}
virtual void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) = 0;
virtual void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) = 0;
{% endif %}
//! MultiplayerController interface
//! @{
Multiplayer::MultiplayerController::InputPriorityOrder GetInputOrder() const override { return Multiplayer::MultiplayerController::InputPriorityOrder::Default; }
AZ::Aabb GetRewindBoundsForInput([[maybe_unused]] const NetworkInput& networkInput, [[maybe_unused]] float deltaTime) const override { return AZ::Aabb::CreateNull(); }
void CreateInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) override {}
void ProcessInput([[maybe_unused]] Multiplayer::NetworkInput& input, [[maybe_unused]] float deltaTime) override {}
//! @}
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Server', false)|indent(8) -}}
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Client', false)|indent(8) -}}
{{ DeclareNetworkPropertyAccessors(Component, 'Authority', 'Autonomous', false)|indent(8) }}
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|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) }}
{{ 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) }}
{% 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 %}
};
static const AZ::Uuid s_{{ LowerFirst(ComponentName) }}ConcreteUuid = "{{ (ComponentName) | createHashGuid }}";
class {{ ComponentBaseName }}{% if not ComponentDerived %} final{% endif %}{{ "" }}
: public Multiplayer::MultiplayerComponent
{
friend class {{ ControllerName }};
friend class {{ ControllerBaseName }};
public:
{% if ComponentDerived %}
AZ_CLASS_ALLOCATOR({{ ComponentBaseName }}, AZ::SystemAllocator, 0);
AZ_RTTI({{ ComponentBaseName }}, s_{{ LowerFirst(ComponentName) }}ConcreteUuid, AZ::Component);
{% else %}
AZ_MULTIPLAYER_COMPONENT({{ Component.attrib['Namespace'] }}::{{ ComponentBaseName }}, s_{{ LowerFirst(ComponentName) }}ConcreteUuid, Multiplayer::MultiplayerComponent);
{% endif %}
static const Multiplayer::NetComponentId s_componentId = static_cast<Multiplayer::NetComponentId>({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }});
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
{{ ComponentBaseName }}() = default;
~{{ ComponentBaseName }}() override = default;
void Init() override;
void Activate() override;
void Deactivate() override;
{% if ComponentDerived %}
virtual void OnInit() = 0;
virtual void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) = 0;
virtual void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) = 0;
{% endif %}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Server', false)|indent(8) -}}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', false)|indent(8) }}
{{ DeclareArchetypePropertyGetters(Component)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', false)|indent(8) }}
//! MultiplayerComponent interface
//! @{
NetComponentId GetNetComponentId() const override;
bool HandleRpcMessage(Multiplayer::NetEntityRole remoteRole, Multiplayer::NetworkEntityRpcMessage& rpcMessage) override;
bool SerializeStateDeltaMessage(Multiplayer::ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer) override;
void NotifyStateDeltaChanges(Multiplayer::ReplicationRecord& replicationRecord) override;
protected:
bool HasController() const override;
MultiplayerController* GetController() override;
void ConstructController() override;
void DestructController() override;
void ActivateController(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void DeactivateController(Multiplayer::EntityIsMigrating entityIsMigrating) override;
void NetworkAttach(Multiplayer::NetBindComponent* netBindComponent, Multiplayer::ReplicationRecord& currentEntityRecord, Multiplayer::ReplicationRecord& predictableEntityRecord) override;
//! @}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Server', true)|indent(8) -}}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Autonomous', true)|indent(8) -}}
{{ DeclareNetworkPropertyGetters(Component, 'Autonomous', 'Authority', true)|indent(8) -}}
{{ DeclareNetworkPropertyGetters(Component, 'Authority', 'Client', true)|indent(8) -}}
{{ DeclareRpcInvocations(Component, 'Server', 'Authority', true)|indent(8) -}}
{{ AutoComponentMacros.DeclareRpcHandlers(Component, 'Authority', 'Client', false)|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;
{{ Service.attrib['Namespace'] }}::{{ Service.attrib['Name'] }}* Get{{ Service.attrib['Name'] }}();
{% endif %}
{% endfor %}
private:
//! Authority to Client serializers
bool SerializeAuthorityToClientProperties({{ RecordName }}& replicationRecord, AzNetworking::ISerializer& serializer);
void NotifyChangesAuthorityToClientProperties(const {{ RecordName }}& replicationRecord) const;
//! Authority To Server serializers
bool SerializeAuthorityToServerProperties({{ RecordName }}& replicationRecord, AzNetworking::ISerializer& serializer);
void NotifyChangesAuthorityToServerProperties(const {{ RecordName }}& replicationRecord) const;
//! Authority To Autonomous serializers
bool SerializeAuthorityToAutonomousProperties({{ RecordName }}& replicationRecord, AzNetworking::ISerializer& serializer);
void NotifyChangesAuthorityToAutonomousProperties(const {{ RecordName }}& replicationRecord) const;
//! Autonomous To Authority serializers
bool SerializeAutonomousToAuthorityProperties({{ RecordName }}& replicationRecord, AzNetworking::ISerializer& serializer);
void NotifyChangesAutonomousToAuthorityProperties(const {{ RecordName }}& replicationRecord) const;
AZStd::unique_ptr<{{ RecordName }}> m_currentRecord;
AZStd::unique_ptr<{{ ControllerName }}> m_controller;
//! Network Properties
{{ DeclareNetworkPropertyVars(Component, 'Authority', 'Server')|indent(8) -}}
{{ DeclareNetworkPropertyVars(Component, 'Authority', 'Client')|indent(8) -}}
{{ DeclareNetworkPropertyVars(Component, 'Authority', 'Autonomous')|indent(8) -}}
{{ DeclareNetworkPropertyVars(Component, 'Autonomous', 'Authority')|indent(8) }}
//! NetworkProperty Events
{{ DeclareNetworkPropertyEvents(Component, 'Authority', 'Server')|indent(8) -}}
{{ DeclareNetworkPropertyEvents(Component, 'Authority', 'Client')|indent(8) -}}
{{ DeclareNetworkPropertyEvents(Component, 'Authority', 'Autonomous')|indent(8) -}}
{{ DeclareNetworkPropertyEvents(Component, 'Autonomous', 'Authority')|indent(8) }}
//! Archetype Properties
{{ DeclareArchetypePropertyVars(Component)|indent(8) }}
{% call(Type, Name) AutoComponentMacros.ParseComponentServiceTypeAndName(Component) %}
{{ Type }}* {{ Name }} = nullptr;
{% endcall %}
};
}
{% endfor %}
File diff suppressed because it is too large Load Diff
@@ -52,6 +52,5 @@
<Member Type="Multiplayer::NetEntityId" Name="entityId" Init="Multiplayer::InvalidNetEntityId" />
<Member Type="Multiplayer::PrefabEntityId" Name="prefabEntityId" Init="" />
<Member Type="AzNetworking::PacketEncodingBuffer" Name="propertyUpdateData" Init="" SuppressFromInitializerList="true" />
<Member Type="AzNetworking::PacketEncodingBuffer" Name="migrationData" Init="" SuppressFromInitializerList="true" />
</Packet>
</PacketGroup>
@@ -0,0 +1,53 @@
<?xml version="1.0"?>
<Component
Name="NetworkTransformComponent"
Namespace="Multiplayer"
OverrideComponent="true"
OverrideController="true"
OverrideInclude="Source/Components/NetworkTransformComponent.h"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ComponentRelation Constraint="Weak" HasController="false" Name="TransformComponent" Namespace="AzFramework" Include="AzFramework/Components/TransformComponent.h" />
<Include File="Source/MultiplayerTypes.h"/>
<NetworkProperty Type="AZ::Quaternion" Name="rotation" Init="AZ::Quaternion::CreateIdentity()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="true" GenerateEventBindings="true" />
<NetworkProperty Type="AZ::Vector3" Name="translation" Init="AZ::Vector3::CreateZero()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="true" GenerateEventBindings="true" />
<NetworkProperty Type="AZ::Vector3" Name="scale" Init="AZ::Vector3::CreateZero()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="true" GenerateEventBindings="true" />
<NetworkProperty Type="AZ::Vector3" Name="velocity" Init="AZ::Vector3::CreateZero()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="true" GenerateEventBindings="true" />
<NetworkProperty Type="uint8_t" Name="resetCount" Init="0" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="false" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
<NetworkProperty Type="NetEntityId" Name="parentEntityId" Init="InvalidNetEntityId" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
<NetworkProperty Type="int32_t" Name="parentAttachmentBoneId" Init="-1" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" GenerateEventBindings="true" />
<ArchetypeProperty Type="bool" Name="snapToGround" Init="false" ExposeToEditor="true" />
<ArchetypeProperty Type="bool" Name="useGroundNormal" Init="false" ExposeToEditor="true" />
<!--
This is reference only, will be deleted when we make a better test component that exercizes all aspects of component autogen
<RemoteProcedure Name="RPCServerToAuthorityPublic" InvokeFrom="Server" HandleOn="Authority" IsPublic="true" IsReliable="false" Description="Description" >
<Param Name="Test" Type="int" DefaultValue="0" Description="Description"/>
</RemoteProcedure>
<RemoteProcedure Name="RPCServerToAuthorityScriptProtected" InvokeFrom="Server" HandleOn="Authority" IsPublic="false" IsReliable="false" Description="Description" >
<Param Name="Test" Type="int" DefaultValue="0" Description="Description"/>
</RemoteProcedure>
<RemoteProcedure Name="RPCAutonomousToAuthorityPublic" InvokeFrom="Autonomous" HandleOn="Authority" IsPublic="true" IsReliable="false" Description="Description" >
<Param Name="Test" Type="int" DefaultValue="0" Description="Description"/>
</RemoteProcedure>
<RemoteProcedure Name="RPCAuthorityToAutonomousPublic" InvokeFrom="Authority" HandleOn="Autonomous" IsPublic="true" IsReliable="false" Description="Description" >
<Param Name="Test" Type="int" DefaultValue="0" Description="Description"/>
</RemoteProcedure>
<RemoteProcedure Name="RpcAuthorityToClientPublic" InvokeFrom="Authority" HandleOn="Client" IsPublic="true" IsReliable="false" Description="Description" >
<Param Name="Test" Type="int" DefaultValue="0" Description="Description"/>
</RemoteProcedure>
<RemoteProcedure Name="RpcAuthorityToClientProtected" InvokeFrom="Authority" HandleOn="Client" IsPublic="false" IsReliable="false" Description="Description" >
<Param Name="Test" Type="int" DefaultValue="0" Description="Description"/>
</RemoteProcedure>
<RemoteProcedure Name="RpcAuthorityToServerPublic" InvokeFrom="Authority" HandleOn="Server" IsPublic="true" IsReliable="true" Description="Description" >
<Param Name="Test" Type="int" DefaultValue="0" Description="Description"/>
</RemoteProcedure>
<RemoteProcedure Name="RpcAuthorityToServerProtected" InvokeFrom="Authority" HandleOn="Server" IsPublic="false" IsReliable="true" Description="Description" >
<Param Name="Test" Type="int" DefaultValue="0" Description="Description"/>
</RemoteProcedure>
-->
</Component>
@@ -58,4 +58,13 @@ namespace Multiplayer
NetBindComponent* netBindComponent = GetNetBindComponent();
return netBindComponent ? netBindComponent->GetEntityHandle() : NetworkEntityHandle();
}
void MultiplayerComponent::MarkDirty()
{
NetBindComponent* netBindComponent = GetNetBindComponent();
if (netBindComponent != nullptr)
{
netBindComponent->MarkDirty();
}
}
}
@@ -14,14 +14,15 @@
#include <AzCore/Component/Component.h>
#include <AzNetworking/Serialization/ISerializer.h>
#include <AzNetworking/DataStructures/FixedSizeBitsetView.h>
#include <Source/NetworkEntity/NetworkEntityHandle.h>
#include <Source/MultiplayerTypes.h>
//! Macro to declare bindings for a multiplayer component inheriting from MultiplayerComponent
#define AZ_MULTIPLAYER_COMPONENT(ComponentClass, Guid) \
AZ_RTTI(ComponentClass, Guid, AZ::Component) \
AZ_COMPONENT_INTRUSIVE_DESCRIPTOR_TYPE(ComponentClass) \
AZ_COMPONENT_BASE(ComponentClass, Guid, Multiplayer::MultiplayerComponent)
#define AZ_MULTIPLAYER_COMPONENT(ComponentClass, Guid, Base) \
AZ_RTTI(ComponentClass, Guid, AZ::Component) \
AZ_COMPONENT_INTRUSIVE_DESCRIPTOR_TYPE(ComponentClass) \
AZ_COMPONENT_BASE(ComponentClass, Guid, Base)
namespace Multiplayer
{
@@ -50,7 +51,7 @@ namespace Multiplayer
NetBindComponent* GetNetBindComponent();
//! @}
//! Linearly searches the components attached to the entity and returns the requested component. .
//! Linearly searches the components attached to the entity and returns the requested component.
//! @return the requested component, or nullptr if the component does not exist on the entity
//! @{
template <typename ComponentType>
@@ -62,25 +63,22 @@ namespace Multiplayer
NetEntityId GetNetEntityId() const;
ConstNetworkEntityHandle GetEntityHandle() const;
NetworkEntityHandle GetEntityHandle();
void MarkDirty();
virtual NetComponentId GetNetComponentId() const = 0;
virtual bool HandleRpcMessage(NetEntityRole netEntityRole, NetworkEntityRpcMessage& rpcMessage) = 0;
virtual bool SerializeStateDeltaMessage(ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer, ComponentSerializationType componentSerializationType) = 0;
virtual void NotifyStateDeltaChanges(ReplicationRecord& replicationRecord, ComponentSerializationType componentSerializationType) = 0;
virtual bool SerializeStateDeltaMessage(ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer) = 0;
virtual void NotifyStateDeltaChanges(ReplicationRecord& replicationRecord) = 0;
protected:
virtual bool HasController() const = 0;
virtual MultiplayerController* GetController() = 0;
virtual bool Migrate(AzNetworking::ISerializer& serializer) = 0;
virtual void ConstructController() = 0;
virtual void DestructController() = 0;
virtual void ActivateController(EntityIsMigrating entityIsMigrating) = 0;
virtual void DeactivateController(EntityIsMigrating entityIsMigrating) = 0;
virtual void NetworkAttach(NetBindComponent& netBindComponent, ReplicationRecord& currentEntityRecord, ReplicationRecord& predictableEntityRecord) = 0;
virtual void NetworkDetach() = 0;
virtual void NetworkAttach(NetBindComponent* netBindComponent, ReplicationRecord& currentEntityRecord, ReplicationRecord& predictableEntityRecord) = 0;
mutable NetBindComponent* m_netBindComponent = nullptr;
@@ -100,4 +98,42 @@ namespace Multiplayer
{
return GetEntity()->FindComponent<ComponentType>();
}
template <typename TYPE>
inline void SerializeNetworkPropertyHelper
(
AzNetworking::ISerializer& serializer,
bool modifyRecord,
AzNetworking::FixedSizeBitsetView& bitset,
int32_t bitIndex,
TYPE& value,
const char* name,
[[maybe_unused]] NetComponentId componentId
)
{
if (bitset.GetBit(bitIndex))
{
//uint32_t prevUpdateSize = serializer.GetSize();
serializer.ClearTrackedChangesFlag();
serializer.Serialize(value, name);
if (modifyRecord && !serializer.GetTrackedChangesFlag())
{
bitset.SetBit(bitIndex, false);
}
//uint32_t postUpdateSize = serializer.GetSize();
// Network Property metrics
// uint32_t updateSize = (postUpdateSize - prevUpdateSize);
// if (updateSize > 0)
// {
// if (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject)
// {
// GetPacketHandlerMetricsInstance().LogRecvNetworkPropertyUpdates(componentType, name, updateSize);
// }
// else
// {
// GetPacketHandlerMetricsInstance().LogSentNetworkPropertyUpdates(componentType, name, updateSize);
// }
// }
}
}
}
@@ -52,10 +52,19 @@ namespace Multiplayer
return m_owner.GetNetBindComponent();
}
const MultiplayerComponent& MultiplayerController::GetOwner() const
{
return m_owner;
}
MultiplayerComponent& MultiplayerController::GetOwner()
{
return m_owner;
}
bool MultiplayerController::IsProcessingInput() const
{
//return m_owner.GetNetBindComponent()->IsProcessingInput();
return false;
return GetNetBindComponent()->IsProcessingInput();
}
MultiplayerController* MultiplayerController::FindController(const AZ::Uuid& typeId, const NetworkEntityHandle& entityHandle) const
@@ -13,6 +13,7 @@
#pragma once
#include <Source/NetworkEntity/NetworkEntityHandle.h>
#include <AzCore/Math/Aabb.h>
namespace Multiplayer
{
@@ -36,6 +37,12 @@ namespace Multiplayer
MultiplayerController(MultiplayerComponent& owner);
virtual ~MultiplayerController() = default;
//! Activates the controller.
virtual void Activate(EntityIsMigrating entityIsMigrating) = 0;
//! Deactivates the controller.
virtual void Deactivate(EntityIsMigrating entityIsMigrating) = 0;
//! Returns the networkId for the entity that owns this controller.
//! @return the networkId for the entity that owns this controller
NetEntityId GetNetEntityId() const;
@@ -54,8 +61,18 @@ namespace Multiplayer
protected:
//! Returns the NetBindComponent responsible for net binding for this controller
//! @{
const NetBindComponent* GetNetBindComponent() const;
NetBindComponent* GetNetBindComponent();
//! @}
//! Returns the MultiplayerComponent that owns this controller instance.
//! @return the MultiplayerComponent that owns this controller instance
//! @{
const MultiplayerComponent& GetOwner() const;
MultiplayerComponent& GetOwner();
//! @}
//! Returns true if the owning entity is currently inside ProcessInput scope.
bool IsProcessingInput() const;
@@ -63,11 +80,11 @@ namespace Multiplayer
//! Returns the input priority ordering for determining the order of ProcessInput or CreateInput functions.
virtual InputPriorityOrder GetInputOrder() const = 0;
//! Hints the rewind system how close an entity should be in order to rewind, this can be very important for performance at scale.
//! Queries the rewind system to determine what volume is relevent for a given input, this is very important for performance at scale.
//! @param networkInput input structure to process
//! @param deltaTime amount of time the provided input would be integrated over
//! @return the maximum distance an entity should be for this component to interact with it given the provided input
virtual float GetRewindDistanceForInput(const NetworkInput& networkInput, float deltaTime) const = 0;
//! @return a world-space aabb representing the volume relevent to the provided input
virtual AZ::Aabb GetRewindBoundsForInput(const NetworkInput& networkInput, float deltaTime) const = 0;
//! Base execution for ProcessInput packet, do not call directly.
//! @param networkInput input structure to process
@@ -75,9 +75,9 @@ namespace Multiplayer
void NetBindComponent::Activate()
{
m_needsToBeStopped = true;
if (m_netEntityRole == NetEntityRole::ServerAuthority)
if (m_netEntityRole == NetEntityRole::Authority)
{
m_handleLocalServerRpcMessageEventHandle.Connect(m_sendServerSimulationtoServerAuthorityRpcEvent);
m_handleLocalServerRpcMessageEventHandle.Connect(m_sendServertoAuthorityRpcEvent);
}
if (NetworkRoleHasController(m_netEntityRole))
{
@@ -98,7 +98,6 @@ namespace Multiplayer
{
GetNetworkEntityManager()->NotifyControllersDeactivated(m_netEntityHandle, EntityIsMigrating::False);
}
NetworkDetach();
}
NetEntityRole NetBindComponent::GetNetEntityRole() const
@@ -108,13 +107,13 @@ namespace Multiplayer
bool NetBindComponent::IsAuthority() const
{
return (m_netEntityRole == NetEntityRole::ServerAuthority);
return (m_netEntityRole == NetEntityRole::Authority);
}
bool NetBindComponent::HasController() const
{
return (m_netEntityRole == NetEntityRole::ServerAuthority)
|| (m_netEntityRole == NetEntityRole::ClientAutonomous);
return (m_netEntityRole == NetEntityRole::Authority)
|| (m_netEntityRole == NetEntityRole::Autonomous);
}
NetEntityId NetBindComponent::GetNetEntityId() const
@@ -160,7 +159,7 @@ namespace Multiplayer
void NetBindComponent::CreateInput(NetworkInput& networkInput, float deltaTime)
{
// Only autonomous or authority runs this logic
AZ_Assert(m_netEntityRole == NetEntityRole::ClientAutonomous || m_netEntityRole == NetEntityRole::ServerAuthority, "Incorrect network role for input creation");
AZ_Assert(m_netEntityRole == NetEntityRole::Autonomous || m_netEntityRole == NetEntityRole::Authority, "Incorrect network role for input creation");
for (MultiplayerComponent* multiplayerComponent : m_multiplayerInputComponentVector)
{
multiplayerComponent->GetController()->CreateInput(networkInput, deltaTime);
@@ -177,15 +176,19 @@ namespace Multiplayer
}
}
float NetBindComponent::GetRewindDistanceForInput(const NetworkInput& networkInput, float deltaTime) const
AZ::Aabb NetBindComponent::GetRewindBoundsForInput(const NetworkInput& networkInput, float deltaTime) const
{
AZ_Assert(m_netEntityRole == NetEntityRole::ServerAuthority, "Incorrect network role for computing rewind distance");
float rewindDistance = 0.0f;
AZ_Assert(m_netEntityRole == NetEntityRole::Authority, "Incorrect network role for computing rewind bounds");
AZ::Aabb bounds = AZ::Aabb::CreateNull();
for (MultiplayerComponent* multiplayerComponent : m_multiplayerInputComponentVector)
{
rewindDistance = AZStd::max(rewindDistance, multiplayerComponent->GetController()->GetRewindDistanceForInput(networkInput, deltaTime));
const AZ::Aabb componentBounds = multiplayerComponent->GetController()->GetRewindBoundsForInput(networkInput, deltaTime);
if (componentBounds.IsValid())
{
bounds.AddAabb(componentBounds);
}
}
return rewindDistance;
return bounds;
}
bool NetBindComponent::HandleRpcMessage(NetEntityRole remoteRole, NetworkEntityRpcMessage& message)
@@ -203,25 +206,25 @@ namespace Multiplayer
const NetEntityRole netEntityRole = m_netEntityRole;
ReplicationRecord replicationRecord(netEntityRole);
replicationRecord.Serialize(serializer);
if ((serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) && (netEntityRole == NetEntityRole::ServerSimulation))
if ((serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) && (netEntityRole == NetEntityRole::Server))
{
// Make sure to capture the entirety of the TotalRecord, before we clear out bits that haven't changed from our local state
// If this entity migrates, we need to send all bits that might have changed from original baseline
m_totalRecord.Append(replicationRecord);
}
// This will modify the replicationRecord and clear out bits that have not changed from the local state, this prevents us from notifying that something has changed multiple times
SerializeStateDeltaMessage(replicationRecord, serializer, ComponentSerializationType::Properties);
SerializeStateDeltaMessage(replicationRecord, serializer);
if (serializer.IsValid())
{
replicationRecord.ResetConsumedBits();
if (notifyChanges)
{
NotifyStateDeltaChanges(replicationRecord, ComponentSerializationType::Properties);
NotifyStateDeltaChanges(replicationRecord);
}
// If we are deserializing on an entity, and this is a server simulation, then we need to remark our bits as dirty to replicate to the client
if ((serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) && (netEntityRole == NetEntityRole::ServerSimulation))
if ((serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) && (netEntityRole == NetEntityRole::Server))
{
m_currentRecord.Append(replicationRecord);
MarkDirty();
@@ -230,24 +233,24 @@ namespace Multiplayer
return serializer.IsValid();
}
RpcSendEvent& NetBindComponent::GetSendServerAuthorityToClientSimulationRpcEvent()
RpcSendEvent& NetBindComponent::GetSendAuthorityToClientRpcEvent()
{
return m_sendServerAuthorityToClientSimulationRpcEvent;
return m_sendAuthorityToClientRpcEvent;
}
RpcSendEvent& NetBindComponent::GetSendServerAuthorityToClientAutonomousRpcEvent()
RpcSendEvent& NetBindComponent::GetSendAuthorityToAutonomousRpcEvent()
{
return m_sendServerAuthorityToClientAutonomousRpcEvent;
return m_sendAuthorityToAutonomousRpcEvent;
}
RpcSendEvent& NetBindComponent::GetSendServerSimulationToServerAuthorityRpcEvent()
RpcSendEvent& NetBindComponent::GetSendServerToAuthorityRpcEvent()
{
return m_sendServerSimulationtoServerAuthorityRpcEvent;
return m_sendServertoAuthorityRpcEvent;
}
RpcSendEvent& NetBindComponent::GetSendClientAutonomousToServerAuthorityRpcEvent()
RpcSendEvent& NetBindComponent::GetSendAutonomousToAuthorityRpcEvent()
{
return m_sendClientAutonomousToServerAuthorityRpcEvent;
return m_sendAutonomousToAuthorityRpcEvent;
}
const ReplicationRecord& NetBindComponent::GetPredictableRecord() const
@@ -266,7 +269,7 @@ namespace Multiplayer
void NetBindComponent::NotifyLocalChanges()
{
m_localNotificationRecord.ResetConsumedBits(); // Make sure our consumed bits are reset so that we can run through the notifications
NotifyStateDeltaChanges(m_localNotificationRecord, ComponentSerializationType::Properties);
NotifyStateDeltaChanges(m_localNotificationRecord);
m_localNotificationRecord.Clear();
}
@@ -297,40 +300,31 @@ namespace Multiplayer
// The m_predictableRecord is a record that that marks every NetworkProperty that has been set as Predictable
// We copy this record and use a temporary so that SerializeStateDeltaMessage will not modify the m_predictableRecord
// since SerializeStateDeltaMessage will clear the dirty bit for the NetworkProperty if it did not actually change
const bool success = SerializeStateDeltaMessage(tmpRecord, serializer, ComponentSerializationType::Correction);
const bool success = SerializeStateDeltaMessage(tmpRecord, serializer);
if (serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject)
{
tmpRecord.ResetConsumedBits();
NotifyStateDeltaChanges(tmpRecord, ComponentSerializationType::Correction);
NotifyStateDeltaChanges(tmpRecord);
}
return success;
}
bool NetBindComponent::SerializeStateDeltaMessage
(
ReplicationRecord& replicationRecord,
AzNetworking::ISerializer& serializer,
ComponentSerializationType componentSerializationType
)
bool NetBindComponent::SerializeStateDeltaMessage(ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer)
{
bool success = true;
for (auto iter = m_multiplayerSerializationComponentVector.begin(); iter != m_multiplayerSerializationComponentVector.end(); ++iter)
{
success &= (*iter)->SerializeStateDeltaMessage(replicationRecord, serializer, componentSerializationType);
success &= (*iter)->SerializeStateDeltaMessage(replicationRecord, serializer);
}
return success;
}
void NetBindComponent::NotifyStateDeltaChanges
(
ReplicationRecord& replicationRecord,
ComponentSerializationType componentSerializationType
)
void NetBindComponent::NotifyStateDeltaChanges(ReplicationRecord& replicationRecord)
{
for (auto iter = m_multiplayerSerializationComponentVector.begin(); iter != m_multiplayerSerializationComponentVector.end(); ++iter)
{
(*iter)->NotifyStateDeltaChanges(replicationRecord, componentSerializationType);
(*iter)->NotifyStateDeltaChanges(replicationRecord);
}
}
@@ -352,27 +346,6 @@ namespace Multiplayer
}
}
bool NetBindComponent::IsMigrationDataValid() const
{
return m_isMigrationDataValid;
}
void NetBindComponent::SetMigrationDataValid(bool migrationDataValid)
{
m_isMigrationDataValid = migrationDataValid;
}
bool NetBindComponent::SerializeMigrationData(AzNetworking::ISerializer& serializer)
{
bool ret = true;
// Purposefully not listed in reverse order, must match the order during construction
for (auto iter = m_multiplayerSerializationComponentVector.begin(); iter != m_multiplayerSerializationComponentVector.end(); ++iter)
{
ret &= (*iter)->Migrate(serializer);
}
return ret && serializer.IsValid();
}
void NetBindComponent::PreInit(AZ::Entity* entity, const PrefabEntityId& prefabEntityId, NetEntityId netEntityId, NetEntityRole netEntityRole)
{
AZ_Assert(entity != nullptr, "AZ::Entity is null");
@@ -404,11 +377,11 @@ namespace Multiplayer
{
switch (m_netEntityRole)
{
case NetEntityRole::ClientSimulation:
m_netEntityRole = NetEntityRole::ClientAutonomous;
case NetEntityRole::Client:
m_netEntityRole = NetEntityRole::Autonomous;
break;
case NetEntityRole::ServerSimulation:
m_netEntityRole = NetEntityRole::ServerAuthority;
case NetEntityRole::Server:
m_netEntityRole = NetEntityRole::Authority;
break;
default:
AZ_Assert(false, "Controller already constructed");
@@ -441,11 +414,11 @@ namespace Multiplayer
switch (m_netEntityRole)
{
case NetEntityRole::ClientAutonomous:
m_netEntityRole = NetEntityRole::ClientSimulation;
case NetEntityRole::Autonomous:
m_netEntityRole = NetEntityRole::Client;
break;
case NetEntityRole::ServerAuthority:
m_netEntityRole = NetEntityRole::ServerSimulation;
case NetEntityRole::Authority:
m_netEntityRole = NetEntityRole::Server;
break;
default:
AZ_Assert(false, "Controllers already destructed");
@@ -465,9 +438,9 @@ namespace Multiplayer
}
}
DetermineInputOrdering();
if (GetNetEntityRole() == NetEntityRole::ServerAuthority)
if (GetNetEntityRole() == NetEntityRole::Authority)
{
m_handleLocalServerRpcMessageEventHandle.Connect(m_sendServerSimulationtoServerAuthorityRpcEvent);
m_handleLocalServerRpcMessageEventHandle.Connect(m_sendServertoAuthorityRpcEvent);
}
GetNetworkEntityManager()->NotifyControllersActivated(m_netEntityHandle, entityIsMigrating);
}
@@ -502,19 +475,11 @@ namespace Multiplayer
{
for (auto* component : m_multiplayerSerializationComponentVector)
{
component->NetworkAttach(*this, m_currentRecord, m_predictableRecord);
component->NetworkAttach(this, m_currentRecord, m_predictableRecord);
}
m_totalRecord = m_currentRecord;
}
void NetBindComponent::NetworkDetach()
{
for (auto* component : m_multiplayerSerializationComponentVector)
{
component->NetworkDetach();
}
}
void NetBindComponent::HandleMarkedDirty()
{
m_dirtiedEvent.Signal();
@@ -532,7 +497,7 @@ namespace Multiplayer
void NetBindComponent::HandleLocalServerRpcMessage(NetworkEntityRpcMessage& message)
{
message.SetRpcDeliveryType(RpcDeliveryType::ServerSimulationToServerAuthority);
message.SetRpcDeliveryType(RpcDeliveryType::ServerToAuthority);
GetNetworkEntityManager()->HandleLocalRpcMessage(message);
}
@@ -574,8 +539,8 @@ namespace Multiplayer
{
switch (networkRole)
{
case NetEntityRole::ClientAutonomous: // Fall through
case NetEntityRole::ServerAuthority:
case NetEntityRole::Autonomous: // Fall through
case NetEntityRole::Authority:
return true;
default:
return false;
@@ -14,6 +14,7 @@
#include <AzCore/Component/Component.h>
#include <AzCore/Component/Entity.h>
#include <AzCore/Math/Aabb.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
@@ -23,6 +24,7 @@
#include <Source/NetworkEntity/NetworkEntityHandle.h>
#include <Source/NetworkInput/IMultiplayerComponentInput.h>
#include <Source/MultiplayerTypes.h>
#include <AzCore/EBus/Event.h>
namespace Multiplayer
{
@@ -68,15 +70,15 @@ namespace Multiplayer
bool IsProcessingInput() const;
void CreateInput(NetworkInput& networkInput, float deltaTime);
void ProcessInput(NetworkInput& networkInput, float deltaTime);
float GetRewindDistanceForInput(const NetworkInput& networkInput, float deltaTime) const;
AZ::Aabb GetRewindBoundsForInput(const NetworkInput& networkInput, float deltaTime) const;
bool HandleRpcMessage(NetEntityRole remoteRole, NetworkEntityRpcMessage& message);
bool HandlePropertyChangeMessage(AzNetworking::ISerializer& serializer, bool notifyChanges = true);
RpcSendEvent& GetSendServerAuthorityToClientSimulationRpcEvent();
RpcSendEvent& GetSendServerAuthorityToClientAutonomousRpcEvent();
RpcSendEvent& GetSendServerSimulationToServerAuthorityRpcEvent();
RpcSendEvent& GetSendClientAutonomousToServerAuthorityRpcEvent();
RpcSendEvent& GetSendAuthorityToClientRpcEvent();
RpcSendEvent& GetSendAuthorityToAutonomousRpcEvent();
RpcSendEvent& GetSendServerToAuthorityRpcEvent();
RpcSendEvent& GetSendAutonomousToAuthorityRpcEvent();
const ReplicationRecord& GetPredictableRecord() const;
@@ -88,20 +90,15 @@ namespace Multiplayer
void AddEntityDirtiedEventHandler(EntityDirtiedEvent::Handler& eventHandler);
void AddEntityMigrationEventHandler(EntityMigrationEvent::Handler& eventHandler);
bool SerializeEntityCorrection(AzNetworking::ISerializer& a_Serializer);
bool SerializeEntityCorrection(AzNetworking::ISerializer& serializer);
bool SerializeStateDeltaMessage(ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer, ComponentSerializationType componentSerializationType);
void NotifyStateDeltaChanges(ReplicationRecord& replicationRecord, ComponentSerializationType componentSerializationType);
bool SerializeStateDeltaMessage(ReplicationRecord& replicationRecord, AzNetworking::ISerializer& serializer);
void NotifyStateDeltaChanges(ReplicationRecord& replicationRecord);
void FillReplicationRecord(ReplicationRecord& replicationRecord) const;
void FillTotalReplicationRecord(ReplicationRecord& replicationRecord) const;
bool IsMigrationDataValid() const;
private:
void SetMigrationDataValid(bool migrationDataValid);
bool SerializeMigrationData(AzNetworking::ISerializer& serializer);
void PreInit(AZ::Entity* entity, const PrefabEntityId& prefabEntityId, NetEntityId netEntityId, NetEntityRole netEntityRole);
void ConstructControllers();
@@ -112,7 +109,6 @@ namespace Multiplayer
void OnEntityStateEvent(AZ::Entity::State oldState, AZ::Entity::State newState);
void NetworkAttach();
void NetworkDetach();
void HandleMarkedDirty();
void HandleLocalServerRpcMessage(NetworkEntityRpcMessage& message);
@@ -130,10 +126,10 @@ namespace Multiplayer
AZStd::vector<MultiplayerComponent*> m_multiplayerSerializationComponentVector;
AZStd::vector<MultiplayerComponent*> m_multiplayerInputComponentVector;
RpcSendEvent m_sendServerAuthorityToClientSimulationRpcEvent;
RpcSendEvent m_sendServerAuthorityToClientAutonomousRpcEvent;
RpcSendEvent m_sendServerSimulationtoServerAuthorityRpcEvent;
RpcSendEvent m_sendClientAutonomousToServerAuthorityRpcEvent;
RpcSendEvent m_sendAuthorityToClientRpcEvent;
RpcSendEvent m_sendAuthorityToAutonomousRpcEvent;
RpcSendEvent m_sendServertoAuthorityRpcEvent;
RpcSendEvent m_sendAutonomousToAuthorityRpcEvent;
EntityStopEvent m_entityStopEvent;
EntityDirtiedEvent m_dirtiedEvent;
@@ -0,0 +1,26 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Source/Components/NetworkTransformComponent.h>
namespace Multiplayer
{
void NetworkTransformComponent::NetworkTransformComponent::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<NetworkTransformComponent, NetworkTransformComponentBase>()
->Version(1);
}
}
}
@@ -0,0 +1,41 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <Source/AutoGen/NetworkTransformComponent.AutoComponent.h>
namespace Multiplayer
{
class NetworkTransformComponent
: public NetworkTransformComponentBase
{
public:
AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkTransformComponent, s_networkTransformComponentConcreteUuid, Multiplayer::NetworkTransformComponentBase);
static void Reflect([[maybe_unused]] AZ::ReflectContext* context);
void OnInit() override {}
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
};
class NetworkTransformComponentController
: public NetworkTransformComponentControllerBase
{
public:
NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) {}
void OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
void OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) override {}
};
}
@@ -71,7 +71,7 @@ namespace Multiplayer
{
NetBindComponent* netBindComponent = m_controlledEntity.GetNetBindComponent();
// 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::ServerAuthority))
if (netBindComponent != nullptr && (netBindComponent->GetNetEntityRole() == NetEntityRole::Authority))
{
m_entityReplicationManager.SendUpdates(serverGameTimeMs);
}
@@ -29,7 +29,7 @@ namespace Multiplayer
, m_entityReplicationManager(*connection, connectionListener, EntityReplicationManager::Mode::LocalServerToRemoteServer)
, m_connectEvent([this]() { OnConnectTimeout(); }, AZ::Name("Server to server connection timeout event"))
{
m_entityReplicationManager.SetRemoteHostId(InvalidHostId);// a_ServerAddrInfo.GetServerAddrInfo().GetShardId());
m_entityReplicationManager.SetRemoteHostId(InvalidHostId);// serverAddrInfo.GetServerAddrInfo().GetShardId());
m_entityReplicationManager.SetEntityActivationTimeSliceMs(sv_DefaultNetworkEntityActivationTimeSliceMs);
m_entityReplicationManager.SetMaxRemoteEntitiesPendingCreationCount(sv_ServerMaxRemoteEntitiesPendingCreationCount);
@@ -60,7 +60,7 @@ namespace Multiplayer
AZ_CVAR(AZ::CVarFixedString, sv_map, "nolevel", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "The map the server should load");
AZ_CVAR(AZ::CVarFixedString, sv_gamerules, "norules", nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "GameRules server works with");
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_isDedicated, true, nullptr, AZ::ConsoleFunctorFlags::DontReplicate, "Whether the host command creates an independent or client hosted server");
void MultiplayerSystemComponent::Reflect(AZ::ReflectContext* context)
{
@@ -375,7 +375,6 @@ namespace Multiplayer
}
}
m_agentType = multiplayerType;
}
void MultiplayerSystemComponent::AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler)
@@ -430,7 +429,7 @@ namespace Multiplayer
void host([[maybe_unused]] const AZ::ConsoleCommandContainer& arguments)
{
Multiplayer::MultiplayerAgentType serverType = sv_isdedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer;
Multiplayer::MultiplayerAgentType serverType = sv_isDedicated ? MultiplayerAgentType::DedicatedServer : MultiplayerAgentType::ClientServer;
INetworkInterface* networkInterface = AZ::Interface<INetworking>::Get()->RetrieveNetworkInterface(AZ::Name(s_networkInterfaceName));
networkInterface->Listen(sv_port);
AZ::Interface<IMultiplayer>::Get()->InitializeMultiplayer(serverType);
@@ -20,6 +20,9 @@
namespace Multiplayer
{
//! The default number of rewindable samples for us to store.
static constexpr uint32_t RewindHistorySize = 128;
AZ_TYPE_SAFE_INTEGRAL(HostId, uint32_t);
static constexpr HostId InvalidHostId = static_cast<HostId>(-1);
@@ -39,19 +42,19 @@ namespace Multiplayer
enum class RpcDeliveryType : uint8_t
{
None,
ServerAuthorityToClientSimulation, // Invoked from ServerAuthority, handled on ClientSimulation
ServerAuthorityToClientAutonomous, // Invoked from ServerAuthority, handled on ClientAutonomous
ClientAutonomousToServerAuthority, // Invoked from ClientAutonomous, handled on ServerAuthority
ServerSimulationToServerAuthority // Invoked from ServerSimulation, handled on ServerAuthority
AuthorityToClient, // Invoked from Authority, handled on Client
AuthorityToAutonomous, // Invoked from Authority, handled on Autonomous
AutonomousToAuthority, // Invoked from Autonomous, handled on Authority
ServerToAuthority // Invoked from Server, handled on Authority
};
enum class NetEntityRole : uint8_t
{
InvalidRole, // No role
ClientSimulation, // A simulated proxy on a client
ClientAutonomous, // An autonomous proxy on a client (can execute local prediction)
ServerSimulation, // A simulated proxy on a server
ServerAuthority // An authoritative proxy on a server (full authority)
InvalidRole, // No role
Client, // A simulated proxy on a client
Autonomous, // An autonomous proxy on a client (can execute local prediction)
Server, // A simulated proxy on a server
Authority // An authoritative proxy on a server (full authority)
};
enum class ComponentSerializationType : uint8_t
@@ -216,7 +216,7 @@ namespace Multiplayer
m_remoteEntitiesPendingCreation.insert(entityId);
}
if (replicator->GetRemoteNetworkRole() == NetEntityRole::ClientAutonomous)
if (replicator->GetRemoteNetworkRole() == NetEntityRole::Autonomous)
{
autonomousReplicators.push_back(replicator);
}
@@ -557,7 +557,7 @@ namespace Multiplayer
const bool changeNetworkRole = (netBindComponent->GetNetEntityRole() != localNetworkRole);
if (changeNetworkRole)
{
AZ_Assert(localNetworkRole != NetEntityRole::ServerAuthority, "UpdateMessage trying to set local role to ServerAuthority, this should only happen via migration");
AZ_Assert(localNetworkRole != NetEntityRole::Authority, "UpdateMessage trying to set local role to Authority, this should only happen via migration");
AZLOG_INFO
(
"EntityReplicationManager: Changing network role on entity %u, old role %u new role %u",
@@ -590,14 +590,14 @@ namespace Multiplayer
// A will tell us to set a timer to delete that entity (since it no longer owns it, and has been handed off), and B will tell us to create it.
// This covers an edge case where the timer has popped, but the entity is pending removal when we are told by B to create the entity.
GetNetworkEntityManager()->ClearEntityFromRemovalList(replicatorEntity);
entityReplicator = AddEntityReplicator(replicatorEntity, NetEntityRole::ServerAuthority);
entityReplicator = AddEntityReplicator(replicatorEntity, NetEntityRole::Authority);
//AZLOG(NET_RepUpdate, "EntityReplicationManager: Created from update entity id %u for type %s role %d", netEntityId, prefabEntityId.GetString(), localNetworkRole);
}
// @nt: TODO - delete once dropped RPC problem fixed
// This code is temporary to work around to the problem that RPC messages are silently lost during migration
// Once this problem is solved, we can remove this code and associated event
if (createReplicator && localNetworkRole == NetEntityRole::ClientAutonomous)
if (createReplicator && localNetworkRole == NetEntityRole::Autonomous)
{
m_autonomousEntityReplicatorCreated.Signal(netEntityId);
}
@@ -647,10 +647,10 @@ namespace Multiplayer
// don't trust the client by default
result = UpdateValidationResult::DropMessageAndDisconnect;
// Clients sending data must have a replicator and be sending in the correct mode, further, they must have a replicator and can never delete a replicator
if (updateMessage.GetNetworkRole() == NetEntityRole::ServerAuthority && entityReplicator && !updateMessage.GetIsDelete())
if (updateMessage.GetNetworkRole() == NetEntityRole::Authority && entityReplicator && !updateMessage.GetIsDelete())
{
// Make sure we our replicator is in the expected configuration
if ((entityReplicator->GetRemoteNetworkRole() == NetEntityRole::ClientAutonomous) && (entityReplicator->GetBoundLocalNetworkRole() == NetEntityRole::ServerAuthority))
if ((entityReplicator->GetRemoteNetworkRole() == NetEntityRole::Autonomous) && (entityReplicator->GetBoundLocalNetworkRole() == NetEntityRole::Authority))
{
// If we're marked for removal, just drop the message - migration message is likely in flight
if (entityReplicator->IsMarkedForRemoval())
@@ -663,7 +663,7 @@ namespace Multiplayer
result = UpdateValidationResult::HandleMessage;
}
} // If we've migrated the entity away from the server, but we get this late, just drop it
else if ((entityReplicator->GetRemoteNetworkRole() == NetEntityRole::ClientSimulation) && (entityReplicator->GetBoundLocalNetworkRole() == NetEntityRole::ServerSimulation))
else if ((entityReplicator->GetRemoteNetworkRole() == NetEntityRole::Client) && (entityReplicator->GetBoundLocalNetworkRole() == NetEntityRole::Server))
{
result = UpdateValidationResult::DropMessage;
}
@@ -686,22 +686,22 @@ namespace Multiplayer
break;
case Mode::LocalServerToRemoteServer:
{
AZ_Assert(updateMessage.GetNetworkRole() == NetEntityRole::ServerSimulation || updateMessage.GetIsDelete(), "Unexpected update type coming from peer server");
AZ_Assert(updateMessage.GetNetworkRole() == NetEntityRole::Server || updateMessage.GetIsDelete(), "Unexpected update type coming from peer server");
// trust messages from a peer server by default
result = UpdateValidationResult::HandleMessage;
// If we have a replicator, make sure we're in the correct state
if (entityReplicator)
{
if (!entityReplicator->IsMarkedForRemoval() && (entityReplicator->GetBoundLocalNetworkRole() == NetEntityRole::ServerAuthority))
if (!entityReplicator->IsMarkedForRemoval() && (entityReplicator->GetBoundLocalNetworkRole() == NetEntityRole::Authority))
{
// Likely an old message from a previous owner trying to delete the replicator it had, while we've received ownership
// This can happen when Shard A migrates an entity to Shard B, then shard B migrates the entity to Shard C, and Shard A tries to delete a replicator it had to Shard C (which has already made a new replicator for Shard A)
result = UpdateValidationResult::DropMessage;
}
else if (entityReplicator->GetRemoteNetworkRole() != NetEntityRole::ServerAuthority)// we expect to the remote role to be e_ServerAuthority
else if (entityReplicator->GetRemoteNetworkRole() != NetEntityRole::Authority)// we expect to the remote role to be e_Authority
{
// This entity has migrated previously, and we haven't heard back that the remove was successful, so we can accept the message
AZ_Assert(entityReplicator->IsMarkedForRemoval() && entityReplicator->GetRemoteNetworkRole() == NetEntityRole::ServerSimulation, "Unexpected server message is not Authority or ServerSimulation");
AZ_Assert(entityReplicator->IsMarkedForRemoval() && entityReplicator->GetRemoteNetworkRole() == NetEntityRole::Server, "Unexpected server message is not Authority or Server");
}
}
}
@@ -1018,9 +1018,9 @@ namespace Multiplayer
AZ_Assert(netBindComponent, "No NetBindComponent");
const EntityReplicator* entityReplicator = GetEntityReplicator(entityHandle.GetNetEntityId());
hasAuthority = (netBindComponent->GetNetEntityRole() == NetEntityRole::ServerAuthority); // Make sure someone hasn't migrated this already
hasAuthority = (netBindComponent->GetNetEntityRole() == NetEntityRole::Authority); // Make sure someone hasn't migrated this already
isInDomain = (m_remoteEntityDomain && m_remoteEntityDomain->IsInDomain(entityHandle)); // Make sure the remote side would want it
if (entityReplicator && entityReplicator->GetBoundLocalNetworkRole() == NetEntityRole::ServerAuthority)
if (entityReplicator && entityReplicator->GetBoundLocalNetworkRole() == NetEntityRole::Authority)
{
isMarkedForRemoval = entityReplicator->IsMarkedForRemoval(); // Make sure we aren't telling the other side to remove the replicator
const PropertyPublisher* propertyPublisher = entityReplicator->GetPropertyPublisher();
@@ -1035,7 +1035,7 @@ namespace Multiplayer
{
if (const EntityReplicator* replicator = GetEntityReplicator(entityHandle.GetNetEntityId()))
{
return replicator->GetRemoteNetworkRole() == NetEntityRole::ServerAuthority;
return replicator->GetRemoteNetworkRole() == NetEntityRole::Authority;
}
return false;
}
@@ -1073,9 +1073,9 @@ namespace Multiplayer
NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
AZ_Assert(netBindComponent, "No NetBindComponent");
if (netBindComponent && netBindComponent->GetNetEntityRole() == NetEntityRole::ServerAuthority)
if (netBindComponent && netBindComponent->GetNetEntityRole() == NetEntityRole::Authority)
{
EntityReplicator* replicator = AddEntityReplicator(entityHandle, NetEntityRole::ServerSimulation);
EntityReplicator* replicator = AddEntityReplicator(entityHandle, NetEntityRole::Server);
PropertyPublisher* propPublisher = replicator->GetPropertyPublisher();
AZ_Assert(propPublisher, "Assumed we have a property publisher");
@@ -1092,15 +1092,11 @@ namespace Multiplayer
if (localEnt->GetState() == AZ::Entity::State::Active)
{
netBindComponent->DeactivateControllers(EntityIsMigrating::True);
AzNetworking::NetworkInputSerializer inputSerializer(message.ModifyMigrationData().GetBuffer(), message.ModifyMigrationData().GetCapacity());
didSucceed = netBindComponent->SerializeMigrationData(inputSerializer);
message.ModifyMigrationData().Resize(inputSerializer.GetSize());
}
netBindComponent->DestructControllers();
netBindComponent->SetMigrationDataValid(false);
// save off network properties after the migration data is saved to capture any changes that might have occurred during deactivate
// Gather the most recent network property state, including authoritative only network properties for migration
{
// Send an update packet if it needs one
propPublisher->GenerateRecord();
@@ -1119,7 +1115,7 @@ namespace Multiplayer
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
AddEntityReplicator(entityHandle, NetEntityRole::ServerAuthority);
AddEntityReplicator(entityHandle, NetEntityRole::Authority);
}
}
@@ -1135,7 +1131,7 @@ namespace Multiplayer
replicator,
AzNetworking::InvalidPacketId,
message.GetEntityId(),
NetEntityRole::ServerSimulation,
NetEntityRole::Server,
outputSerializer,
message.GetPrefabEntityId()
))
@@ -1159,15 +1155,6 @@ namespace Multiplayer
// Stop listening to the OnEntityNetworkRoleChange, since we are about to change it and we don't want that callback
netBindComponent->ConstructControllers();
bool didSucceed = false;
{
AzNetworking::NetworkOutputSerializer outputSerializer(message.ModifyMigrationData().GetBuffer(), message.ModifyMigrationData().GetSize());
didSucceed = netBindComponent->SerializeMigrationData(outputSerializer);
AZ_Assert(didSucceed, "Failed to migrate entity to server");
AZ_Assert(outputSerializer.IsValid() && outputSerializer.GetUnreadSize() == 0, "Bad migration");
}
netBindComponent->SetMigrationDataValid(true);
if (entityHandle.GetEntity()->GetState() == AZ::Entity::State::Active)
{
// Only activate controllers if the entity was previously activated, otherwise, wait for the normal entity activation flow
@@ -1175,10 +1162,10 @@ namespace Multiplayer
}
// change the role on the replicator
AddEntityReplicator(entityHandle, NetEntityRole::ServerSimulation);
AddEntityReplicator(entityHandle, NetEntityRole::Server);
AZLOG(NET_RepDeletes, "Handle Migration %u new authority from remote manager id %d", entityHandle.GetNetEntityId(), aznumeric_cast<int32_t>(GetRemoteHostId()));
return didSucceed;
return true;
}
void EntityReplicationManager::OnEntityExitDomain(const ConstNetworkEntityHandle& entityHandle)
@@ -50,8 +50,8 @@ namespace Multiplayer
, m_onEntityDirtiedHandler([this]() { OnEntityDirtiedEvent(); })
, m_onSendRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); })
, m_onForwardRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); })
, m_onSendClientAutonomousRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); })
, m_onForwardClientAutonomousRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); })
, m_onSendAutonomousRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); })
, m_onForwardAutonomousRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); })
, m_onEntityStopHandler([this](const ConstNetworkEntityHandle &) { OnEntityRemovedEvent(); })
, m_proxyRemovalEvent([this] { OnProxyRemovalTimedEvent(); }, AZ::Name("ProxyRemovalTimedEvent"))
{
@@ -73,11 +73,11 @@ namespace Multiplayer
m_prefabEntityIdSet = true;
}
void EntityReplicator::Reset(NetEntityRole a_RemoteNetworkRole)
void EntityReplicator::Reset(NetEntityRole remoteNetworkRole)
{
AZ::EntityBus::Handler::BusDisconnect();
m_remoteNetworkRole = a_RemoteNetworkRole;
m_remoteNetworkRole = remoteNetworkRole;
m_propertyPublisher = nullptr;
m_propertySubscriber = nullptr;
@@ -86,8 +86,8 @@ namespace Multiplayer
m_onSendRpcHandler.Disconnect();
m_onForwardRpcHandler.Disconnect();
m_onSendClientAutonomousRpcHandler.Disconnect();
m_onForwardClientAutonomousRpcHandler.Disconnect();
m_onSendAutonomousRpcHandler.Disconnect();
m_onForwardAutonomousRpcHandler.Disconnect();
m_onEntityStopHandler.Disconnect();
}
@@ -136,8 +136,8 @@ namespace Multiplayer
m_propertyPublisher = nullptr;
}
if (m_remoteNetworkRole == NetEntityRole::ServerAuthority ||
m_remoteNetworkRole == NetEntityRole::ClientAutonomous)
if (m_remoteNetworkRole == NetEntityRole::Authority ||
m_remoteNetworkRole == NetEntityRole::Autonomous)
{
m_propertySubscriber = AZStd::make_unique<PropertySubscriber>(m_replicationManager, m_netBindComponent);
}
@@ -165,9 +165,9 @@ namespace Multiplayer
{
// Make sure all handlers are detached first
m_onSendRpcHandler.Disconnect();
m_onSendClientAutonomousRpcHandler.Disconnect();
m_onSendAutonomousRpcHandler.Disconnect();
m_onForwardRpcHandler.Disconnect();
m_onForwardClientAutonomousRpcHandler.Disconnect();
m_onForwardAutonomousRpcHandler.Disconnect();
if (auto localEntity = m_entityHandle.GetEntity())
{
@@ -176,49 +176,49 @@ namespace Multiplayer
switch (GetBoundLocalNetworkRole())
{
case NetEntityRole::ServerAuthority:
case NetEntityRole::Authority:
{
if (GetRemoteNetworkRole() == NetEntityRole::ClientSimulation || GetRemoteNetworkRole() == NetEntityRole::ClientAutonomous)
if (GetRemoteNetworkRole() == NetEntityRole::Client || GetRemoteNetworkRole() == NetEntityRole::Autonomous)
{
m_onSendRpcHandler.Connect(netBindComponent->GetSendServerAuthorityToClientSimulationRpcEvent());
if (GetRemoteNetworkRole() == NetEntityRole::ClientAutonomous)
m_onSendRpcHandler.Connect(netBindComponent->GetSendAuthorityToClientRpcEvent());
if (GetRemoteNetworkRole() == NetEntityRole::Autonomous)
{
m_onSendClientAutonomousRpcHandler.Connect(netBindComponent->GetSendServerAuthorityToClientAutonomousRpcEvent());
m_onSendAutonomousRpcHandler.Connect(netBindComponent->GetSendAuthorityToAutonomousRpcEvent());
}
}
else if (GetRemoteNetworkRole() == NetEntityRole::ServerSimulation)
else if (GetRemoteNetworkRole() == NetEntityRole::Server)
{
m_onForwardRpcHandler.Connect(netBindComponent->GetSendServerAuthorityToClientSimulationRpcEvent());
m_onForwardRpcHandler.Connect(netBindComponent->GetSendAuthorityToClientRpcEvent());
}
}
break;
case NetEntityRole::ServerSimulation:
case NetEntityRole::Server:
{
if (GetRemoteNetworkRole() == NetEntityRole::ServerAuthority)
if (GetRemoteNetworkRole() == NetEntityRole::Authority)
{
m_onSendRpcHandler.Connect(netBindComponent->GetSendServerSimulationToServerAuthorityRpcEvent());
m_onForwardRpcHandler.Connect(netBindComponent->GetSendServerAuthorityToClientSimulationRpcEvent());
m_onForwardClientAutonomousRpcHandler.Connect(netBindComponent->GetSendServerAuthorityToClientAutonomousRpcEvent());
m_onSendRpcHandler.Connect(netBindComponent->GetSendServerToAuthorityRpcEvent());
m_onForwardRpcHandler.Connect(netBindComponent->GetSendAuthorityToClientRpcEvent());
m_onForwardAutonomousRpcHandler.Connect(netBindComponent->GetSendAuthorityToAutonomousRpcEvent());
}
else if (GetRemoteNetworkRole() == NetEntityRole::ClientSimulation)
else if (GetRemoteNetworkRole() == NetEntityRole::Client)
{
// Listen for these to forward the rpc along to the other Client replicators
m_onSendRpcHandler.Connect(netBindComponent->GetSendServerAuthorityToClientSimulationRpcEvent());
m_onSendRpcHandler.Connect(netBindComponent->GetSendAuthorityToClientRpcEvent());
}
// NOTE: e_ClientAutonomous is not connected to e_ServerProxy, it is always connected to an e_ServerAuthority
AZ_Assert(GetRemoteNetworkRole() != NetEntityRole::ClientAutonomous, "Unexpected autonomous remote role")
// NOTE: e_Autonomous is not connected to e_ServerProxy, it is always connected to an e_Authority
AZ_Assert(GetRemoteNetworkRole() != NetEntityRole::Autonomous, "Unexpected autonomous remote role")
}
break;
case NetEntityRole::ClientSimulation:
case NetEntityRole::Client:
{
// Nothing allowed, no ClientSimulation to Server communication
// Nothing allowed, no Client to Server communication
}
break;
case NetEntityRole::ClientAutonomous:
case NetEntityRole::Autonomous:
{
if (GetRemoteNetworkRole() == NetEntityRole::ServerAuthority)
if (GetRemoteNetworkRole() == NetEntityRole::Authority)
{
m_onSendRpcHandler.Connect(netBindComponent->GetSendClientAutonomousToServerAuthorityRpcEvent());
m_onSendRpcHandler.Connect(netBindComponent->GetSendAutonomousToAuthorityRpcEvent());
}
}
break;
@@ -282,11 +282,11 @@ namespace Multiplayer
NetBindComponent* netBindComponent = m_netBindComponent;
AZ_Assert(netBindComponent, "No Multiplayer::NetBindComponent");
bool isServerAuthority = (GetBoundLocalNetworkRole() == NetEntityRole::ServerAuthority)
bool isAuthority = (GetBoundLocalNetworkRole() == NetEntityRole::Authority)
&& (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole());
bool isClientSimulation = GetRemoteNetworkRole() == NetEntityRole::ClientSimulation;
bool isClientAutonomous = GetBoundLocalNetworkRole() == NetEntityRole::ClientAutonomous;
if (isServerAuthority || isClientSimulation || isClientAutonomous)
bool isClient = GetRemoteNetworkRole() == NetEntityRole::Client;
bool isAutonomous = GetBoundLocalNetworkRole() == NetEntityRole::Autonomous;
if (isAuthority || isClient || isAutonomous)
{
ret = true;
}
@@ -297,10 +297,10 @@ namespace Multiplayer
bool EntityReplicator::OwnsReplicatorLifetime() const
{
bool ret(false);
if (GetBoundLocalNetworkRole() == NetEntityRole::ServerAuthority
|| (GetBoundLocalNetworkRole() == NetEntityRole::ServerSimulation
&& (GetRemoteNetworkRole() == NetEntityRole::ClientSimulation
|| GetRemoteNetworkRole() == NetEntityRole::ClientAutonomous)))
if (GetBoundLocalNetworkRole() == NetEntityRole::Authority
|| (GetBoundLocalNetworkRole() == NetEntityRole::Server
&& (GetRemoteNetworkRole() == NetEntityRole::Client
|| GetRemoteNetworkRole() == NetEntityRole::Autonomous)))
{
ret = true;
}
@@ -310,11 +310,11 @@ namespace Multiplayer
bool EntityReplicator::RemoteManagerOwnsEntityLifetime() const
{
bool ret(false);
bool isServerSimulation = (GetBoundLocalNetworkRole() == NetEntityRole::ServerSimulation)
&& (GetRemoteNetworkRole() == NetEntityRole::ServerAuthority);
bool isClientSimulation = (GetBoundLocalNetworkRole() == NetEntityRole::ClientSimulation)
|| (GetBoundLocalNetworkRole() == NetEntityRole::ClientAutonomous);
if (isServerSimulation || isClientSimulation)
bool isServer = (GetBoundLocalNetworkRole() == NetEntityRole::Server)
&& (GetRemoteNetworkRole() == NetEntityRole::Authority);
bool isClient = (GetBoundLocalNetworkRole() == NetEntityRole::Client)
|| (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous);
if (isServer || isClient)
{
ret = true;
}
@@ -346,7 +346,7 @@ namespace Multiplayer
m_replicationManager.AddReplicatorToPendingRemoval(*this);
m_onForwardRpcHandler.Disconnect();
m_onForwardClientAutonomousRpcHandler.Disconnect();
m_onForwardAutonomousRpcHandler.Disconnect();
m_onEntityStopHandler.Disconnect();
}
@@ -492,32 +492,32 @@ namespace Multiplayer
RpcValidationResult result = RpcValidationResult::DropRpcAndDisconnect;
switch (entityRpcMessage.GetRpcDeliveryType())
{
case RpcDeliveryType::ServerAuthorityToClientSimulation:
case RpcDeliveryType::AuthorityToClient:
{
if (((GetBoundLocalNetworkRole() == NetEntityRole::ClientSimulation) || (GetBoundLocalNetworkRole() == NetEntityRole::ClientAutonomous))
&& (GetRemoteNetworkRole() == NetEntityRole::ServerAuthority))
if (((GetBoundLocalNetworkRole() == NetEntityRole::Client) || (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous))
&& (GetRemoteNetworkRole() == NetEntityRole::Authority))
{
// We are a local client, and we are connected to server, aka AuthorityToClient
result = RpcValidationResult::HandleRpc;
}
if ((GetBoundLocalNetworkRole() == NetEntityRole::ServerSimulation)
&& (GetRemoteNetworkRole() == NetEntityRole::ServerAuthority))
if ((GetBoundLocalNetworkRole() == NetEntityRole::Server)
&& (GetRemoteNetworkRole() == NetEntityRole::Authority))
{
// We are on a server, and we received this message from another server, therefore we should forward this to any connected clients
result = RpcValidationResult::ForwardToClient;
}
}
break;
case RpcDeliveryType::ServerAuthorityToClientAutonomous:
case RpcDeliveryType::AuthorityToAutonomous:
{
if ((GetBoundLocalNetworkRole() == NetEntityRole::ClientAutonomous)
&& (GetRemoteNetworkRole() == NetEntityRole::ServerAuthority))
if ((GetBoundLocalNetworkRole() == NetEntityRole::Autonomous)
&& (GetRemoteNetworkRole() == NetEntityRole::Authority))
{
// We are an autonomous client, and we are connected to server, aka AuthorityToAutonomous
result = RpcValidationResult::HandleRpc;
}
if ((GetBoundLocalNetworkRole() == NetEntityRole::ServerAuthority)
&& (GetRemoteNetworkRole() == NetEntityRole::ServerSimulation))
if ((GetBoundLocalNetworkRole() == NetEntityRole::Authority)
&& (GetRemoteNetworkRole() == NetEntityRole::Server))
{
// We are on a server, and we received this message from another server, therefore we should forward this to our autonomous player
// This can occur if we've recently migrated
@@ -525,10 +525,10 @@ namespace Multiplayer
}
}
break;
case RpcDeliveryType::ClientAutonomousToServerAuthority:
case RpcDeliveryType::AutonomousToAuthority:
{
if ((GetBoundLocalNetworkRole() == NetEntityRole::ServerAuthority)
&& (GetRemoteNetworkRole() == NetEntityRole::ClientAutonomous))
if ((GetBoundLocalNetworkRole() == NetEntityRole::Authority)
&& (GetRemoteNetworkRole() == NetEntityRole::Autonomous))
{
if (IsMarkedForRemoval())
{
@@ -552,10 +552,10 @@ namespace Multiplayer
}
}
break;
case RpcDeliveryType::ServerSimulationToServerAuthority:
case RpcDeliveryType::ServerToAuthority:
{
if ((GetBoundLocalNetworkRole() == NetEntityRole::ServerAuthority)
&& (GetRemoteNetworkRole() == NetEntityRole::ServerSimulation))
if ((GetBoundLocalNetworkRole() == NetEntityRole::Authority)
&& (GetRemoteNetworkRole() == NetEntityRole::Server))
{
// if we're marked for removal, then we should forward to whomever now owns this entity
if (IsMarkedForRemoval())
@@ -583,8 +583,8 @@ namespace Multiplayer
}
if (result == RpcValidationResult::DropRpcAndDisconnect)
{
bool isLocalServer = (GetBoundLocalNetworkRole() == NetEntityRole::ServerAuthority) || (GetBoundLocalNetworkRole() == NetEntityRole::ServerSimulation);
bool isRemoteServer = (GetRemoteNetworkRole() == NetEntityRole::ServerAuthority) || (GetRemoteNetworkRole() == NetEntityRole::ServerSimulation);
bool isLocalServer = (GetBoundLocalNetworkRole() == NetEntityRole::Authority) || (GetBoundLocalNetworkRole() == NetEntityRole::Server);
bool isRemoteServer = (GetRemoteNetworkRole() == NetEntityRole::Authority) || (GetRemoteNetworkRole() == NetEntityRole::Server);
if (isLocalServer && isRemoteServer)
{
// Demote this to just a drop message, we didn't want to handle the message, but we don't want to drop the connection
@@ -680,19 +680,19 @@ namespace Multiplayer
case RpcValidationResult::ForwardToClient:
{
ScopedForwardingMessage forwarding(*this);
m_netBindComponent->GetSendServerAuthorityToClientSimulationRpcEvent().Signal(entityRpcMessage);
m_netBindComponent->GetSendAuthorityToClientRpcEvent().Signal(entityRpcMessage);
return true;
}
case RpcValidationResult::ForwardToAutonomous:
{
ScopedForwardingMessage forwarding(*this);
m_netBindComponent->GetSendServerAuthorityToClientAutonomousRpcEvent().Signal(entityRpcMessage);
m_netBindComponent->GetSendAuthorityToAutonomousRpcEvent().Signal(entityRpcMessage);
return true;
}
case RpcValidationResult::ForwardToAuthority:
{
ScopedForwardingMessage forwarding(*this);
m_netBindComponent->GetSendServerSimulationToServerAuthorityRpcEvent().Signal(entityRpcMessage);
m_netBindComponent->GetSendServerToAuthorityRpcEvent().Signal(entityRpcMessage);
return true;
}
default:
@@ -119,8 +119,8 @@ namespace Multiplayer
// Events
RpcSendEvent::Handler m_onSendRpcHandler;
RpcSendEvent::Handler m_onForwardRpcHandler;
RpcSendEvent::Handler m_onSendClientAutonomousRpcHandler;
RpcSendEvent::Handler m_onForwardClientAutonomousRpcHandler;
RpcSendEvent::Handler m_onSendAutonomousRpcHandler;
RpcSendEvent::Handler m_onForwardAutonomousRpcHandler;
EntityDirtiedEvent::Handler m_onEntityDirtiedHandler;
EntityStopEvent::Handler m_onEntityStopHandler;
AZ::ScheduledEvent m_proxyRemovalEvent;
@@ -67,7 +67,7 @@ namespace Multiplayer
void PropertyPublisher::SetRebasing()
{
AZ_Assert(m_pendingRecord.GetNetworkRole() == NetEntityRole::ClientAutonomous, "Expected to be rebasing on a ClientAutonomous entity");
AZ_Assert(m_pendingRecord.GetNetworkRole() == NetEntityRole::Autonomous, "Expected to be rebasing on a Autonomous entity");
m_replicatorState = EntityReplicatorState::Rebasing;
}
@@ -117,8 +117,8 @@ namespace Multiplayer
// This is basically an Add record, but we don't want to send back predictable values
m_sentRecords.clear();
m_netBindComponent->FillTotalReplicationRecord(m_pendingRecord);
// Don't send predictable properties back to the ClientAutonomous unless we correct them
if (m_pendingRecord.GetNetworkRole() == NetEntityRole::ClientAutonomous)
// Don't send predictable properties back to the Autonomous unless we correct them
if (m_pendingRecord.GetNetworkRole() == NetEntityRole::Autonomous)
{
m_pendingRecord.Subtract(m_netBindComponent->GetPredictableRecord());
}
@@ -144,8 +144,8 @@ namespace Multiplayer
m_pendingRecord.Append(*iter);
}
// Don't send predictable properties back to the ClientAutonomous unless we correct them
if (m_pendingRecord.GetNetworkRole() == NetEntityRole::ClientAutonomous)
// Don't send predictable properties back to the Autonomous unless we correct them
if (m_pendingRecord.GetNetworkRole() == NetEntityRole::Autonomous)
{
m_pendingRecord.Subtract(m_netBindComponent->GetPredictableRecord());
}
@@ -165,7 +165,7 @@ namespace Multiplayer
AZ_Assert(m_netBindComponent, "NetBindComponent is nullptr");
m_pendingRecord.ResetConsumedBits();
m_pendingRecord.Serialize(serializer);
m_netBindComponent->SerializeStateDeltaMessage(m_pendingRecord, serializer, ComponentSerializationType::Properties);
m_netBindComponent->SerializeStateDeltaMessage(m_pendingRecord, serializer);
return serializer.IsValid();
}
@@ -67,10 +67,10 @@ namespace Multiplayer
bool ReplicationRecord::AreAllBitsConsumed() const
{
bool ret = true;
ret &= m_authorityToClientConsumedBits == m_authorityToClientRecord.GetSize();
ret &= m_authorityToServerConsumedBits == m_authorityToServerRecord.GetSize();
ret &= m_authorityToAutonomousConsumedBits == m_authorityToAutonomousRecord.GetSize();
ret &= m_autonomousToAuthorityConsumedBits == m_autonomousToAuthorityRecord.GetSize();
ret &= m_authorityToClientConsumedBits == m_authorityToClient.GetSize();
ret &= m_authorityToServerConsumedBits == m_authorityToServer.GetSize();
ret &= m_authorityToAutonomousConsumedBits == m_authorityToAutonomous.GetSize();
ret &= m_autonomousToAuthorityConsumedBits == m_autonomousToAuthority.GetSize();
return ret;
}
@@ -86,37 +86,37 @@ namespace Multiplayer
{
ResetConsumedBits();
uint32_t recordSize = m_authorityToClientRecord.GetSize();
m_authorityToClientRecord.Clear();
m_authorityToClientRecord.Resize(recordSize);
uint32_t recordSize = m_authorityToClient.GetSize();
m_authorityToClient.Clear();
m_authorityToClient.Resize(recordSize);
recordSize = m_authorityToServerRecord.GetSize();
m_authorityToServerRecord.Clear();
m_authorityToServerRecord.Resize(recordSize);
recordSize = m_authorityToServer.GetSize();
m_authorityToServer.Clear();
m_authorityToServer.Resize(recordSize);
recordSize = m_authorityToAutonomousRecord.GetSize();
m_authorityToAutonomousRecord.Clear();
m_authorityToAutonomousRecord.Resize(recordSize);
recordSize = m_authorityToAutonomous.GetSize();
m_authorityToAutonomous.Clear();
m_authorityToAutonomous.Resize(recordSize);
recordSize = m_autonomousToAuthorityRecord.GetSize();
m_autonomousToAuthorityRecord.Clear();
m_autonomousToAuthorityRecord.Resize(recordSize);
recordSize = m_autonomousToAuthority.GetSize();
m_autonomousToAuthority.Clear();
m_autonomousToAuthority.Resize(recordSize);
}
void ReplicationRecord::Append(const ReplicationRecord &rhs)
{
m_authorityToClientRecord |= rhs.m_authorityToClientRecord;
m_authorityToServerRecord |= rhs.m_authorityToServerRecord;
m_authorityToAutonomousRecord |= rhs.m_authorityToAutonomousRecord;
m_autonomousToAuthorityRecord |= rhs.m_autonomousToAuthorityRecord;
m_authorityToClient |= rhs.m_authorityToClient;
m_authorityToServer |= rhs.m_authorityToServer;
m_authorityToAutonomous |= rhs.m_authorityToAutonomous;
m_autonomousToAuthority |= rhs.m_autonomousToAuthority;
}
void ReplicationRecord::Subtract(const ReplicationRecord &rhs)
{
m_authorityToClientRecord.Subtract(rhs.m_authorityToClientRecord);
m_authorityToServerRecord.Subtract(rhs.m_authorityToServerRecord);
m_authorityToAutonomousRecord.Subtract(rhs.m_authorityToAutonomousRecord);
m_autonomousToAuthorityRecord.Subtract(rhs.m_autonomousToAuthorityRecord);
m_authorityToClient.Subtract(rhs.m_authorityToClient);
m_authorityToServer.Subtract(rhs.m_authorityToServer);
m_authorityToAutonomous.Subtract(rhs.m_authorityToAutonomous);
m_autonomousToAuthority.Subtract(rhs.m_autonomousToAuthority);
}
bool ReplicationRecord::HasChanges() const
@@ -124,42 +124,42 @@ namespace Multiplayer
bool hasChanges(false);
if (ContainsAuthorityToClientBits())
{
hasChanges = hasChanges ? hasChanges : m_authorityToClientRecord.AnySet();
hasChanges = hasChanges ? hasChanges : m_authorityToClient.AnySet();
}
if (ContainsAuthorityToServerBits())
{
hasChanges = hasChanges ? hasChanges : m_authorityToServerRecord.AnySet();
hasChanges = hasChanges ? hasChanges : m_authorityToServer.AnySet();
}
if (ContainsAuthorityToAutonomousBits())
{
hasChanges = hasChanges ? hasChanges : m_authorityToAutonomousRecord.AnySet();
hasChanges = hasChanges ? hasChanges : m_authorityToAutonomous.AnySet();
}
if (ContainsAutonomousToAuthorityBits())
{
hasChanges = hasChanges ? hasChanges : m_autonomousToAuthorityRecord.AnySet();
hasChanges = hasChanges ? hasChanges : m_autonomousToAuthority.AnySet();
}
return hasChanges;
}
bool ReplicationRecord::Serialize(AzNetworking::ISerializer& a_Serializer)
bool ReplicationRecord::Serialize(AzNetworking::ISerializer& serializer)
{
if (ContainsAuthorityToClientBits())
{
a_Serializer.Serialize(m_authorityToClientRecord, "ServerToClientsRecord");
serializer.Serialize(m_authorityToClient, "ServerToClientsRecord");
}
if (ContainsAuthorityToServerBits())
{
a_Serializer.Serialize(m_authorityToServerRecord, "ServerToServersRecord");
serializer.Serialize(m_authorityToServer, "ServerToServersRecord");
}
if (ContainsAuthorityToAutonomousBits())
{
a_Serializer.Serialize(m_authorityToAutonomousRecord, "ServerToClientAutonomousRecord");
serializer.Serialize(m_authorityToAutonomous, "ServerToAutonomousRecord");
}
if (ContainsAutonomousToAuthorityBits())
{
a_Serializer.Serialize(m_autonomousToAuthorityRecord, "ClientToServersRecord");
serializer.Serialize(m_autonomousToAuthority, "ClientToServersRecord");
}
return a_Serializer.IsValid();
return serializer.IsValid();
}
void ReplicationRecord::ConsumeAuthorityToClientBits(uint32_t consumedBits)
@@ -196,46 +196,46 @@ namespace Multiplayer
bool ReplicationRecord::ContainsAuthorityToClientBits() const
{
return (m_netEntityRole != NetEntityRole::ServerAuthority)
return (m_netEntityRole != NetEntityRole::Authority)
|| (m_netEntityRole == NetEntityRole::InvalidRole);
}
bool ReplicationRecord::ContainsAuthorityToServerBits() const
{
return (m_netEntityRole == NetEntityRole::ServerSimulation)
return (m_netEntityRole == NetEntityRole::Server)
|| (m_netEntityRole == NetEntityRole::InvalidRole);
}
bool ReplicationRecord::ContainsAuthorityToAutonomousBits() const
{
return (m_netEntityRole == NetEntityRole::ClientAutonomous || m_netEntityRole == NetEntityRole::ServerSimulation)
return (m_netEntityRole == NetEntityRole::Autonomous || m_netEntityRole == NetEntityRole::Server)
|| (m_netEntityRole == NetEntityRole::InvalidRole);
}
bool ReplicationRecord::ContainsAutonomousToAuthorityBits() const
{
return (m_netEntityRole == NetEntityRole::ServerAuthority)
return (m_netEntityRole == NetEntityRole::Authority)
|| (m_netEntityRole == NetEntityRole::InvalidRole);
}
uint32_t ReplicationRecord::GetRemainingAuthorityToClientBits() const
{
return m_authorityToClientConsumedBits < m_authorityToClientRecord.GetValidBitCount() ? m_authorityToClientRecord.GetValidBitCount() - m_authorityToClientConsumedBits : 0;
return m_authorityToClientConsumedBits < m_authorityToClient.GetValidBitCount() ? m_authorityToClient.GetValidBitCount() - m_authorityToClientConsumedBits : 0;
}
uint32_t ReplicationRecord::GetRemainingAuthorityToServerBits() const
{
return m_authorityToServerConsumedBits < m_authorityToServerRecord.GetValidBitCount() ? m_authorityToServerRecord.GetValidBitCount() - m_authorityToServerConsumedBits : 0;
return m_authorityToServerConsumedBits < m_authorityToServer.GetValidBitCount() ? m_authorityToServer.GetValidBitCount() - m_authorityToServerConsumedBits : 0;
}
uint32_t ReplicationRecord::GetRemainingAuthorityToAutonomousBits() const
{
return m_authorityToAutonomousConsumedBits < m_authorityToAutonomousRecord.GetValidBitCount() ? m_authorityToAutonomousRecord.GetValidBitCount() - m_authorityToAutonomousConsumedBits : 0;
return m_authorityToAutonomousConsumedBits < m_authorityToAutonomous.GetValidBitCount() ? m_authorityToAutonomous.GetValidBitCount() - m_authorityToAutonomousConsumedBits : 0;
}
uint32_t ReplicationRecord::GetRemainingAutonomousToAuthorityBits() const
{
return m_autonomousToAuthorityConsumedBits < m_autonomousToAuthorityRecord.GetValidBitCount() ? m_autonomousToAuthorityRecord.GetValidBitCount() - m_autonomousToAuthorityConsumedBits : 0;
return m_autonomousToAuthorityConsumedBits < m_autonomousToAuthority.GetValidBitCount() ? m_autonomousToAuthority.GetValidBitCount() - m_autonomousToAuthorityConsumedBits : 0;
}
ReplicationRecordStats ReplicationRecord::GetStats() const
@@ -79,10 +79,10 @@ namespace Multiplayer
ReplicationRecordStats GetStats() const;
using RecordBitset = AzNetworking::FixedSizeVectorBitset<MaxRecordBits>;
RecordBitset m_authorityToClientRecord;
RecordBitset m_authorityToServerRecord;
RecordBitset m_authorityToAutonomousRecord;
RecordBitset m_autonomousToAuthorityRecord;
RecordBitset m_authorityToClient;
RecordBitset m_authorityToServer;
RecordBitset m_authorityToAutonomous;
RecordBitset m_autonomousToAuthority;
uint32_t m_authorityToClientConsumedBits = 0;
uint32_t m_authorityToServerConsumedBits = 0;
@@ -103,7 +103,7 @@ namespace Multiplayer
{
networkRole = netBindComponent->GetNetEntityRole();
}
if (networkRole != NetEntityRole::ClientAutonomous)
if (networkRole != NetEntityRole::Autonomous)
{
AZ_Assert
(
@@ -118,7 +118,7 @@ namespace Multiplayer
}
else
{
AZLOG(NET_AuthTracker, "AuthTracker: Skipping timeout for ClientAutonomous networkEntityId %u", aznumeric_cast<uint32_t>(entityHandle.GetNetEntityId()));
AZLOG(NET_AuthTracker, "AuthTracker: Skipping timeout for Autonomous networkEntityId %u", aznumeric_cast<uint32_t>(entityHandle.GetNetEntityId()));
}
}
}
@@ -152,7 +152,7 @@ namespace Multiplayer
{
networkRole = netBindComponent->GetNetEntityRole();
}
if (networkRole == NetEntityRole::ServerAuthority)
if (networkRole == NetEntityRole::Authority)
{
return m_networkEntityManager.GetHostId();
}
@@ -205,7 +205,7 @@ namespace Multiplayer
{
networkRole = netBindComponent->GetNetEntityRole();
}
if (networkRole != NetEntityRole::ServerAuthority)
if (networkRole != NetEntityRole::Authority)
{
AZLOG_ERROR
(
@@ -181,7 +181,7 @@ namespace Multiplayer
void NetworkEntityManager::HandleLocalRpcMessage(NetworkEntityRpcMessage& message)
{
AZ_Assert(message.GetRpcDeliveryType() == RpcDeliveryType::ServerSimulationToServerAuthority, "Only ServerSimulationToServerAuthority rpc messages can be locally deferred");
AZ_Assert(message.GetRpcDeliveryType() == RpcDeliveryType::ServerToAuthority, "Only ServerToAuthority rpc messages can be locally deferred");
m_localDeferredRpcMessages.emplace_back(AZStd::move(message));
}
@@ -56,8 +56,8 @@ namespace Multiplayer
RpcDeliveryType GetRpcDeliveryType() const;
//! Sets the current value for RpcDeliveryType.
//! @param a_Value the value to set RpcDeliveryType to
void SetRpcDeliveryType(RpcDeliveryType a_Value);
//! @param value the value to set RpcDeliveryType to
void SetRpcDeliveryType(RpcDeliveryType value);
//! Gets the current value of EntityId.
//! @return the current value of EntityId
@@ -72,7 +72,7 @@ namespace Multiplayer
uint8_t GetRpcMessageType() const;
//! Writes the data contained inside a_Params to this NetworkEntityRpcMessage's blob buffer.
//! @param a_Params the parameters to save inside this NetworkEntityRpcMessage instance
//! @param params the parameters to save inside this NetworkEntityRpcMessage instance
bool SetRpcParams(IRpcParamStruct& params);
//! Reads the data contained inside this NetworkEntityRpcMessage's blob buffer and stores them in outParams.
@@ -36,7 +36,7 @@ namespace Multiplayer
const NetworkInput& GetNetworkInput() const;
NetworkInput& GetNetworkInput();
bool Serialize(AzNetworking::ISerializer& a_Serializer);
bool Serialize(AzNetworking::ISerializer& serializer);
private:
ConstNetworkEntityHandle m_owner;
NetworkInput m_networkInput;
@@ -33,7 +33,7 @@ namespace Multiplayer
//! Constructor.
//! @param connectionId the connectionId of the connection that owns the object.
RewindableObject(AzNetworking::ConnectionId owningConnectionId);
RewindableObject(const BASE_TYPE& value);
//! Copy construct from underlying base type.
//! @param value base type value to construct from
@@ -52,6 +52,10 @@ namespace Multiplayer
//! @param rhs rewindable history buffer to assign from
RewindableObject& operator = (const RewindableObject& rhs);
//! Sets the owning connectionId for the given rewindable object instance.
//! @param owningConnectionId the new connectionId to use as the owning connectionId.
void SetOwningConnectionId(AzNetworking::ConnectionId owningConnectionId);
//! Const base type operator.
//! @return value in const base type form
operator const BASE_TYPE&() const;
@@ -106,4 +110,9 @@ namespace Multiplayer
};
}
namespace AZ
{
AZ_TYPE_INFO_TEMPLATE(Multiplayer::RewindableObject, "{B2937B44-FEE1-4277-B1E0-863DE76D363F}", AZ_TYPE_INFO_TYPENAME, AZ_TYPE_INFO_AUTO);
}
#include <Source/NetworkTime/RewindableObject.inl>
@@ -15,10 +15,9 @@
namespace Multiplayer
{
template <typename BASE_TYPE, AZStd::size_t REWIND_SIZE>
inline RewindableObject<BASE_TYPE, REWIND_SIZE>::RewindableObject(AzNetworking::ConnectionId owningConnectionId)
: m_owningConnectionId(owningConnectionId)
inline RewindableObject<BASE_TYPE, REWIND_SIZE>::RewindableObject(const BASE_TYPE& value)
{
m_history.fill(BASE_TYPE());
m_history.fill(value);
}
template <typename BASE_TYPE, AZStd::size_t REWIND_SIZE>
@@ -53,6 +52,12 @@ namespace Multiplayer
return *this;
}
template <typename BASE_TYPE, AZStd::size_t REWIND_SIZE>
inline void RewindableObject<BASE_TYPE, REWIND_SIZE>::SetOwningConnectionId(AzNetworking::ConnectionId owningConnectionId)
{
m_owningConnectionId = owningConnectionId;
}
template <typename BASE_TYPE, AZStd::size_t REWIND_SIZE>
inline RewindableObject<BASE_TYPE, REWIND_SIZE>::operator const BASE_TYPE& () const
{
@@ -165,8 +165,8 @@ namespace Multiplayer
}
// Add in Autonomous Entities
// Note: Do not add any ClientSimulation entities after this point, otherwise you stomp over the ClientAutonomous mode
m_replicationSet[m_controlledEntity] = { NetEntityRole::ClientAutonomous, 1.0f }; // Always replicate autonomous entities
// Note: Do not add any Client entities after this point, otherwise you stomp over the Autonomous mode
m_replicationSet[m_controlledEntity] = { NetEntityRole::Autonomous, 1.0f }; // Always replicate autonomous entities
//auto hierarchyController = FindController<EntityHierarchyComponent::Authority>(m_ControlledEntity);
//if (hierarchyController != nullptr)
@@ -277,7 +277,7 @@ namespace Multiplayer
if (!sv_ReplicateServerProxies)
{
NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent();
if ((netBindComponent != nullptr) && (netBindComponent->GetNetEntityRole() == NetEntityRole::ServerSimulation))
if ((netBindComponent != nullptr) && (netBindComponent->GetNetEntityRole() == NetEntityRole::Server))
{
// Proxy replication disabled
return;
@@ -296,28 +296,28 @@ namespace Multiplayer
m_replicationSet.erase(removeEnt);
}
m_candidateQueue.push(PrioritizedReplicationCandidate(entityHandle, priority));
m_replicationSet[entityHandle] = { NetEntityRole::ClientSimulation, priority };
m_replicationSet[entityHandle] = { NetEntityRole::Client, priority };
}
}
//void ServerToClientReplicationWindow::CollectControlledEntitiesRecursive(ReplicationSet& a_ReplicationSet, EntityHierarchyComponent::Authority& a_HierarchyController)
//void ServerToClientReplicationWindow::CollectControlledEntitiesRecursive(ReplicationSet& replicationSet, EntityHierarchyComponent::Authority& hierarchyController)
//{
// auto controlledEnts = a_HierarchyController.GetChildrenRelatedEntities();
// auto controlledEnts = hierarchyController.GetChildrenRelatedEntities();
// for (auto& controlledEnt : controlledEnts)
// {
// AZ_Assert(controlledEnt != nullptr, "We have lost a controlled entity unexpectedly");
// a_ReplicationSet[controlledEnt.GetConstEntity()] = EntityReplicationData(EntityNetworkRoleT::e_ClientAutonomous, EntityPrioritySystem::k_MaxPriority); // Always replicate controlled entities
// replicationSet[controlledEnt.GetConstEntity()] = EntityReplicationData(EntityNetworkRoleT::e_Autonomous, EntityPrioritySystem::k_MaxPriority); // Always replicate controlled entities
// auto hierarchyController = controlledEnt.FindController<EntityHierarchyComponent::Authority>();
// if (hierarchyController != nullptr)
// {
// CollectControlledEntitiesRecursive(a_ReplicationSet, *hierarchyController);
// CollectControlledEntitiesRecursive(replicationSet, *hierarchyController);
// }
// }
//}
//void ServerToClientReplicationWindow::OnAddFilteredEntity(NetEntityId a_FitleredEntityId)
//void ServerToClientReplicationWindow::OnAddFilteredEntity(NetEntityId filteredEntityId)
//{
// ConstEntityPtr filteredEntity = gNovaGame->GetEntityManager().GetEntity(a_FitleredEntityId);
// m_replicationSet.erase(filteredEntity);
// ConstEntityPtr filteredEntity = gNovaGame->GetEntityManager().GetEntity(filteredEntityId);
// m_replicationSet.erase(filteredEntityId);
//}
}
@@ -62,26 +62,26 @@ namespace Multiplayer
void OnEntityDeactivated(const AZ::EntityId&) override;
//! @}
//void CollectControlledEntitiesRecursive(ReplicationSet& a_ReplicationSet, EntityHierarchyComponent::Authority& a_HierarchyController);
//void OnAddFilteredEntity(EntityIdT a_FitleredEntityId);
//void CollectControlledEntitiesRecursive(ReplicationSet& replicationSet, EntityHierarchyComponent::Authority& hierarchyController);
//void OnAddFilteredEntity(NetEntityId filteredEntityId);
void EvaluateConnection();
void AddEntityToReplicationSet(ConstNetworkEntityHandle& entityHandle, float priority, float distanceSquared);
ServerToClientReplicationWindow& operator=(const ServerToClientReplicationWindow&) = delete;
NetworkEntityHandle m_controlledEntity;
AZ::TransformInterface* m_controlledEntityTransform = nullptr;
//FilteredEntityComponent::Authority* mp_ControlledFilteredEntityComponent = nullptr;
//NetSystemComponent* mp_ControlledNetSystemComponent = nullptr;
// sorted in reverse, lowest priority is the top()
ReplicationCandidateQueue m_candidateQueue;
ReplicationSet m_replicationSet;
AZ::ScheduledEvent m_updateWindowEvent;
NetworkEntityHandle m_controlledEntity;
AZ::TransformInterface* m_controlledEntityTransform = nullptr;
//FilteredEntityComponent::Authority* m_controlledFilteredEntityComponent = nullptr;
//NetBindComponent* m_controlledNetBindComponent = nullptr;
const AzNetworking::IConnection* m_connection = nullptr;
float m_minPriorityReplicated = 0.0f; ///< Lowest replicated entity priority in last update
@@ -55,14 +55,14 @@ namespace Multiplayer
if (netBindComponent != nullptr)
{
NetEntityRole networkRole = netBindComponent->GetNetEntityRole();
if (networkRole == NetEntityRole::ServerAuthority)
if (networkRole == NetEntityRole::Authority)
{
const AZ::Entity* entity = entityHandle.GetEntity();
AZ::TransformInterface* transformInterface = entity->GetTransform();
AZ::Vector3 entityPosition = transformInterface->GetWorldTranslation();
if (m_aabb.Contains(entityPosition))
{
outNetworkRole = Multiplayer::NetEntityRole::ServerSimulation;
outNetworkRole = Multiplayer::NetEntityRole::Server;
return true;
}
}
@@ -88,9 +88,9 @@ namespace Multiplayer
if (netBindComponent != nullptr)
{
NetEntityRole networkRole = netBindComponent->GetNetEntityRole();
if (networkRole == NetEntityRole::ServerAuthority)
if (networkRole == NetEntityRole::Authority)
{
m_replicationSet[entityHandle] = { NetEntityRole::ServerSimulation, 0.0f }; // Note, server replication does not use priority
m_replicationSet[entityHandle] = { NetEntityRole::Server, 0.0f }; // Note, server replication does not use priority
}
}
}
@@ -130,7 +130,7 @@ namespace Multiplayer
NetEntityRole networkRole = NetEntityRole::InvalidRole;
if (IsInWindow(entityHandle, networkRole))
{
m_replicationSet[entityHandle] = { NetEntityRole::ServerSimulation, 0.0f };
m_replicationSet[entityHandle] = { NetEntityRole::Server, 0.0f };
}
}