Merging latest origin/main
This commit is contained in:
@@ -37,7 +37,7 @@ namespace Multiplayer
|
||||
|
||||
void OnRotationChangedEvent(const AZ::Quaternion& rotation);
|
||||
void OnTranslationChangedEvent(const AZ::Vector3& translation);
|
||||
void OnScaleChangedEvent(const AZ::Vector3& scale);
|
||||
void OnScaleChangedEvent(float scale);
|
||||
void OnResetCountChangedEvent();
|
||||
|
||||
AZ::Transform m_previousTransform = AZ::Transform::CreateIdentity();
|
||||
@@ -45,7 +45,7 @@ namespace Multiplayer
|
||||
|
||||
AZ::Event<AZ::Quaternion>::Handler m_rotationEventHandler;
|
||||
AZ::Event<AZ::Vector3>::Handler m_translationEventHandler;
|
||||
AZ::Event<AZ::Vector3>::Handler m_scaleEventHandler;
|
||||
AZ::Event<float>::Handler m_scaleEventHandler;
|
||||
AZ::Event<uint8_t>::Handler m_resetCountEventHandler;
|
||||
|
||||
EntityPreRenderEvent::Handler m_entityPreRenderEventHandler;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 <AzCore/std/containers/array.h>
|
||||
#include <AzNetworking/DataStructures/IBitset.h>
|
||||
#include <AzNetworking/Serialization/ISerializer.h>
|
||||
|
||||
#include <Multiplayer/NetworkTime/RewindableObject.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
//! @class RewindableArray
|
||||
//! @brief Data structure that has a compile-time upper bound, provides array semantics and supports network serialization
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
class RewindableArray
|
||||
: public AZStd::array<RewindableObject<TYPE, Multiplayer::RewindHistorySize>, SIZE>
|
||||
{
|
||||
public:
|
||||
//! Serialization method for array contained rewindable objects
|
||||
//! @param serializer ISerializer instance to use for serialization
|
||||
//! @return bool true for success, false for serialization failure
|
||||
bool Serialize(AzNetworking::ISerializer& serializer);
|
||||
|
||||
//! Serialization method for array contained rewindable objects
|
||||
//! @param serializer ISerializer instance to use for serialization
|
||||
//! @param deltaRecord Bitset delta record used to detect state change during reconciliation
|
||||
//! @return bool true for success, false for serialization failure
|
||||
bool Serialize(AzNetworking::ISerializer& serializer, AzNetworking::IBitset &deltaRecord);
|
||||
};
|
||||
}
|
||||
|
||||
#include <Multiplayer/NetworkTime/RewindableArray.inl>
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
bool RewindableArray<TYPE, SIZE>::Serialize(AzNetworking::ISerializer& serializer)
|
||||
{
|
||||
for (uint32_t i = 0; i < SIZE; ++i)
|
||||
{
|
||||
if(!this[i].Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return serializer.IsValid();
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
bool RewindableArray<TYPE, SIZE>::Serialize(AzNetworking::ISerializer& serializer, AzNetworking::IBitset& deltaRecord)
|
||||
{
|
||||
for (uint32_t i = 0; i < SIZE; ++i)
|
||||
{
|
||||
if (deltaRecord.GetBit(i))
|
||||
{
|
||||
serializer.ClearTrackedChangesFlag();
|
||||
if(!this[i].Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) && !serializer.GetTrackedChangesFlag())
|
||||
{
|
||||
deltaRecord.SetBit(i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return serializer.IsValid();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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 <AzCore/std/containers/array.h>
|
||||
#include <AzNetworking/DataStructures/IBitset.h>
|
||||
#include <AzNetworking/Serialization/ISerializer.h>
|
||||
|
||||
#include <Multiplayer/NetworkTime/RewindableObject.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
//! @class RewindableFixedVector
|
||||
//! @brief Data structure that has a compile-time upper bound, provides vector semantics and supports network serialization
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
class RewindableFixedVector
|
||||
{
|
||||
public:
|
||||
//! Default constructor
|
||||
constexpr RewindableFixedVector() = default;
|
||||
|
||||
//! Construct and initialize buffer to the provided value
|
||||
//! @param initialValue initial value to set the internal buffer to
|
||||
//! @param count initial value to reserve in the vector
|
||||
constexpr RewindableFixedVector(const TYPE& initialValue, uint32_t count);
|
||||
|
||||
//! Destructor
|
||||
~RewindableFixedVector();
|
||||
|
||||
//! Serialization method for fixed vector contained rewindable objects
|
||||
//! @param serializer ISerializer instance to use for serialization
|
||||
//! @return bool true for success, false for serialization failure
|
||||
bool Serialize(AzNetworking::ISerializer& serializer);
|
||||
|
||||
//! Serialization method for fixed vector contained rewindable objects
|
||||
//! @param serializer ISerializer instance to use for serialization
|
||||
//! @param deltaRecord Bitset delta record used to detect state change during reconciliation
|
||||
//! @return bool true for success, false for serialization failure
|
||||
bool Serialize(AzNetworking::ISerializer& serializer, AzNetworking::IBitset &deltaRecord);
|
||||
|
||||
//! Copies elements from the buffer pointed to by Buffer to this FixedSizeVector instance, vector size will be set to BufferSize
|
||||
//! @param buffer pointer to the buffer to copy
|
||||
//! @param bufferSize number of elements in the buffer to copy
|
||||
//! @return bool true on success, false if the input data was too large to fit in the vector
|
||||
constexpr bool copy_values(const TYPE* buffer, uint32_t bufferSize);
|
||||
|
||||
//! Copy buffer from the provided vector
|
||||
//! @param RHS instance to copy from
|
||||
constexpr RewindableFixedVector<TYPE, SIZE>& operator=(const RewindableFixedVector<TYPE, SIZE>& rhs);
|
||||
|
||||
//! Equality operator, returns true if the current instance is equal to RHS
|
||||
//! @param rhs the FixedSizeVector instance to test for equality against
|
||||
//! @return bool true if equal, false if not
|
||||
constexpr bool operator ==(const RewindableFixedVector<TYPE, SIZE>& rhs) const;
|
||||
|
||||
//! Inequality operator, returns true if the current instance is not equal to RHS
|
||||
//! @param rhs the FixedSizeVector instance to test for inequality against
|
||||
//! @return bool false if equal, true if not equal
|
||||
constexpr bool operator !=(const RewindableFixedVector<TYPE, SIZE>& rhs) const;
|
||||
|
||||
//! Resizes the vector to the requested number of elements, initializing new elements if necessary
|
||||
//! @param count the number of elements to size the vector to
|
||||
//! @return bool true on success
|
||||
constexpr bool resize(uint32_t count);
|
||||
|
||||
//! Resizes the vector to the requested number of elements, without initialization
|
||||
//! @param count the number of elements to size the vector to
|
||||
//! @return bool true on success
|
||||
constexpr bool resize_no_construct(uint32_t count);
|
||||
|
||||
//! Resets the vector, returning it to size 0
|
||||
constexpr void clear();
|
||||
|
||||
//! Const element access
|
||||
//! @param Index index of the element to return
|
||||
//! @return const reference to the requested element
|
||||
constexpr const TYPE& operator[](uint32_t index) const;
|
||||
|
||||
//! Non-const element access
|
||||
//! @param Index index of the element to return
|
||||
//! @return non-const reference to the requested element
|
||||
constexpr TYPE& operator[](uint32_t index);
|
||||
|
||||
//! Pushes a new element to the back of the vector
|
||||
//! @param Value value to append to the back of this vector
|
||||
//! @return boolean true on success, false if the vector was full
|
||||
constexpr bool push_back(const TYPE& value);
|
||||
|
||||
//! Pops the last element off the vector, decreasing the vector's size by one
|
||||
//! @return bool true on success, false if the vector was empty
|
||||
constexpr bool pop_back();
|
||||
|
||||
//! Returns if the vector is empty
|
||||
//! @return bool true on empty, false if the vector contains valid elements
|
||||
constexpr bool empty() const;
|
||||
|
||||
//! Gets the last element of the vector
|
||||
constexpr const TYPE& back() const;
|
||||
|
||||
//! Gets the size of the vector
|
||||
constexpr uint32_t size() const;
|
||||
|
||||
typedef const RewindableObject<TYPE, Multiplayer::RewindHistorySize>* const_iterator;
|
||||
const_iterator begin() const { return m_container.cbegin(); }
|
||||
const_iterator end() const { return m_container.cbegin() + aznumeric_cast<size_t>(size()); }
|
||||
typedef RewindableObject<TYPE, Multiplayer::RewindHistorySize>* iterator;
|
||||
constexpr iterator begin() { return m_container.begin(); }
|
||||
constexpr iterator end() { return m_container.begin() + aznumeric_cast<size_t>(size()); }
|
||||
|
||||
private:
|
||||
AZStd::array<RewindableObject<TYPE, Multiplayer::RewindHistorySize>, SIZE> m_container;
|
||||
// Synchronized value for vector size, prefer using size() locally which checks m_container.size()
|
||||
RewindableObject<uint32_t, Multiplayer::RewindHistorySize> m_rewindableSize;
|
||||
};
|
||||
}
|
||||
|
||||
#include <Multiplayer/NetworkTime/RewindableFixedVector.inl>
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr RewindableFixedVector<TYPE, SIZE>::RewindableFixedVector(const TYPE& initialValue, uint32_t count)
|
||||
{
|
||||
m_container.fill(initialValue);
|
||||
m_rewindableSize = count;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
RewindableFixedVector<TYPE, SIZE>::~RewindableFixedVector()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
bool RewindableFixedVector<TYPE, SIZE>::Serialize(AzNetworking::ISerializer& serializer)
|
||||
{
|
||||
if(!m_rewindableSize.Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t idx = 0; idx < size(); ++idx)
|
||||
{
|
||||
if(!m_container[idx].Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return serializer.IsValid();
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
bool RewindableFixedVector<TYPE, SIZE>::Serialize(AzNetworking::ISerializer& serializer, AzNetworking::IBitset& deltaRecord)
|
||||
{
|
||||
if (deltaRecord.GetBit(SIZE))
|
||||
{
|
||||
const uint32_t origSize = m_rewindableSize;
|
||||
if(!m_rewindableSize.Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) && origSize == m_rewindableSize)
|
||||
{
|
||||
deltaRecord.SetBit(SIZE, false);
|
||||
}
|
||||
}
|
||||
for (uint32_t idx = 0; idx < size(); ++idx)
|
||||
{
|
||||
if (deltaRecord.GetBit(idx))
|
||||
{
|
||||
serializer.ClearTrackedChangesFlag();
|
||||
if(!m_container[idx].Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) && !serializer.GetTrackedChangesFlag())
|
||||
{
|
||||
deltaRecord.SetBit(idx, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return serializer.IsValid();
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr bool RewindableFixedVector<TYPE, SIZE>::copy_values(const TYPE* buffer, uint32_t bufferSize)
|
||||
{
|
||||
if (!resize(bufferSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t idx = 0; idx < bufferSize; ++idx)
|
||||
{
|
||||
m_container[idx] = buffer[idx];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr RewindableFixedVector<TYPE, SIZE>& RewindableFixedVector<TYPE, SIZE>::operator=(const RewindableFixedVector<TYPE, SIZE>& rhs)
|
||||
{
|
||||
resize(rhs.size());
|
||||
for (uint32_t idx = 0; idx < size(); ++idx)
|
||||
{
|
||||
m_container[idx] = rhs.m_container[idx].Get();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr bool RewindableFixedVector<TYPE, SIZE>::operator ==(const RewindableFixedVector<TYPE, SIZE>& rhs) const
|
||||
{
|
||||
return m_container == rhs.m_container && m_rewindableSize == rhs.m_rewindableSize;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr bool RewindableFixedVector<TYPE, SIZE>::operator !=(const RewindableFixedVector<TYPE, SIZE>& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr bool RewindableFixedVector<TYPE, SIZE>::resize(uint32_t count)
|
||||
{
|
||||
if (count > SIZE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count == size())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (count > size())
|
||||
{
|
||||
for (uint32_t idx = size(); idx < count; ++idx)
|
||||
{
|
||||
m_container[idx] = TYPE();
|
||||
}
|
||||
}
|
||||
m_rewindableSize = count;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr bool RewindableFixedVector<TYPE, SIZE>::resize_no_construct(uint32_t count)
|
||||
{
|
||||
if (count > SIZE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_rewindableSize = count;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr void RewindableFixedVector<TYPE, SIZE>::clear()
|
||||
{
|
||||
for (uint32_t idx = 0; idx < SIZE; ++idx)
|
||||
{
|
||||
m_container[idx] = TYPE();
|
||||
}
|
||||
m_rewindableSize = 0;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr const TYPE& RewindableFixedVector<TYPE, SIZE>::operator[](uint32_t index) const
|
||||
{
|
||||
AZ_Assert(index < size(), "Out of bounds access (requested %u, reserved %u)", index, size());
|
||||
return m_container[index].Get();
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr TYPE& RewindableFixedVector<TYPE, SIZE>::operator[](uint32_t index)
|
||||
{
|
||||
AZ_Assert(index < size(), "Out of bounds access (requested %u, reserved %u)", index, size());
|
||||
return m_container[index].Modify();
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr bool RewindableFixedVector<TYPE, SIZE>::push_back(const TYPE& value)
|
||||
{
|
||||
if (size() < SIZE)
|
||||
{
|
||||
m_container[m_rewindableSize] = value;
|
||||
m_rewindableSize = m_rewindableSize + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr bool RewindableFixedVector<TYPE, SIZE>::pop_back()
|
||||
{
|
||||
if (size() > 0)
|
||||
{
|
||||
m_rewindableSize = m_rewindableSize - 1;
|
||||
m_container[m_rewindableSize] = TYPE();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr bool RewindableFixedVector<TYPE, SIZE>::empty() const
|
||||
{
|
||||
return m_rewindableSize.Get() == 0;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr const TYPE& RewindableFixedVector<TYPE, SIZE>::back() const
|
||||
{
|
||||
AZ_Assert(size() > 0, "Attempted to get back element of an empty RewindableFixedVector");
|
||||
return m_container[m_rewindableSize - 1].Get();
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr uint32_t RewindableFixedVector<TYPE, SIZE>::size() const
|
||||
{
|
||||
return m_rewindableSize;
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ namespace Multiplayer
|
||||
RewindableObject() = default;
|
||||
|
||||
//! Constructor.
|
||||
//! @param connectionId the connectionId of the connection that owns the object.
|
||||
//! @param value base type value to construct from
|
||||
RewindableObject(const BASE_TYPE& value);
|
||||
|
||||
//! Copy construct from underlying base type.
|
||||
|
||||
@@ -7,13 +7,21 @@
|
||||
{% macro DeclareNetworkPropertyGetter(Property) %}
|
||||
{% set PropertyName = UpperFirst(Property.attrib['Name']) %}
|
||||
{% if Property.attrib['Container'] == 'Array' %}
|
||||
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;
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
const RewindableArray<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> &Get{{ PropertyName }}Array() const;
|
||||
{% else %}
|
||||
const AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> &Get{{ PropertyName }}Array() const;
|
||||
{% endif %}
|
||||
const {{ Property.attrib['Type'] }} &Get{{ PropertyName }}(int32_t index) const;
|
||||
{% if Property.attrib['GenerateEventBindings']|booleanTrue %}
|
||||
void {{ PropertyName }}AddEvent(AZ::Event<int32_t, {{ Property.attrib['Type'] }}>::Handler& handler);
|
||||
{% endif %}
|
||||
{% elif Property.attrib['Container'] == 'Vector' %}
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
const RewindableFixedVector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> &Get{{ PropertyName }}Vector() const;
|
||||
{% else %}
|
||||
const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> &Get{{ PropertyName }}Vector() const;
|
||||
{% endif %}
|
||||
const {{ Property.attrib['Type'] }} &Get{{ PropertyName }}(int32_t index) const;
|
||||
const {{ Property.attrib['Type'] }} &{{ PropertyName }}GetBack() const;
|
||||
uint32_t {{ PropertyName }}GetSize() const;
|
||||
@@ -156,9 +164,17 @@ AZ::Event<{{ Property.attrib['Type'] }}> m_{{ LowerFirst(Property.attrib['Name']
|
||||
{% 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_{{ LowerFirst(Property.attrib['Name']) }};
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
RewindableArray<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> m_{{ LowerFirst(Property.attrib['Name']) }};
|
||||
{% else %}
|
||||
AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> m_{{ LowerFirst(Property.attrib['Name']) }};
|
||||
{% endif %}
|
||||
{% elif Property.attrib['Container'] == 'Vector' %}
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
RewindableFixedVector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> m_{{ LowerFirst(Property.attrib['Name']) }};
|
||||
{% else %}
|
||||
AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> m_{{ LowerFirst(Property.attrib['Name']) }};
|
||||
{% endif %}
|
||||
{% elif Property.attrib['IsRewindable']|booleanTrue %}
|
||||
Multiplayer::RewindableObject<{{ Property.attrib['Type'] }}, Multiplayer::RewindHistorySize> m_{{ LowerFirst(Property.attrib['Name']) }} = {{ Property.attrib['Init'] }};
|
||||
{% else %}
|
||||
@@ -228,6 +244,8 @@ AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }
|
||||
#include <Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h>
|
||||
#include <Multiplayer/NetworkInput/IMultiplayerComponentInput.h>
|
||||
#include <Multiplayer/NetworkInput/NetworkInput.h>
|
||||
#include <Multiplayer/NetworkTime/RewindableArray.h>
|
||||
#include <Multiplayer/NetworkTime/RewindableFixedVector.h>
|
||||
#include <Multiplayer/NetworkTime/RewindableObject.h>
|
||||
{% call(Include) AutoComponentMacros.ParseIncludes(Component) %}
|
||||
#include <{{ Include.attrib['File'] }}>
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
{% macro LowerFirst(text) %}{{ text[0] | lower}}{{ text[1:] }}{% endmacro %}
|
||||
{% macro DefineNetworkPropertyGet(ClassName, Property, Prefix = '') %}
|
||||
{% if Property.attrib['Container'] == 'Array' %}
|
||||
const AZStd::array<{% if Property.attrib['IsRewindable']|booleanTrue %}Multiplayer::RewindableObject<{% endif %}{{ Property.attrib['Type'] }}{% if Property.attrib['IsRewindable']|booleanTrue %}, Multiplayer::RewindHistorySize>{% endif %}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Array() const
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
const RewindableArray<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Array() const
|
||||
{% else %}
|
||||
const AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Array() const
|
||||
{% endif %}
|
||||
{
|
||||
return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }};
|
||||
}
|
||||
@@ -21,7 +25,11 @@ void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}AddEvent(AZ::Even
|
||||
|
||||
{% endif %}
|
||||
{% elif Property.attrib['Container'] == 'Vector' %}
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
const RewindableFixedVector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Vector() const
|
||||
{% else %}
|
||||
const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Vector() const
|
||||
{% endif %}
|
||||
{
|
||||
return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }};
|
||||
}
|
||||
@@ -110,25 +118,26 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index
|
||||
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const {{ Property.attrib['Type'] }} &value)
|
||||
{
|
||||
int32_t indexToSet = GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.size();
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.push_back(value);
|
||||
int32_t bitIndex = indexToSet + static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return true;
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.push_back(value))
|
||||
{
|
||||
int32_t indexToSet = GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.size();
|
||||
int32_t bitIndex = indexToSet + static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PopBack(const Multiplayer::NetworkInput&)
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.empty())
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.pop_back())
|
||||
{
|
||||
return false;
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return true;
|
||||
}
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.pop_back();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}Clear(const Multiplayer::NetworkInput&)
|
||||
@@ -207,25 +216,27 @@ void {{ ClassName }}::Set{{ UpperFirst(Property.attrib['Name']) }}(int32_t index
|
||||
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PushBack(const {{ Property.attrib['Type'] }} &value)
|
||||
{
|
||||
uint32_t indexToSet = aznumeric_cast<uint32_t>(GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.size());
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.push_back(value);
|
||||
uint32_t bitIndex = indexToSet + aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return true;
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.push_back(value))
|
||||
{
|
||||
uint32_t indexToSet = aznumeric_cast<uint32_t>(GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.size());
|
||||
uint32_t bitIndex = indexToSet + aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(bitIndex, true);
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(aznumeric_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}PopBack()
|
||||
{
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.empty())
|
||||
if (GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.pop_back())
|
||||
{
|
||||
return false;
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
return true;
|
||||
}
|
||||
GetParent().m_currentRecord->m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.SetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }}), true);
|
||||
GetParent().MarkDirty();
|
||||
GetParent().m_{{ LowerFirst(Property.attrib['Name']) }}.pop_back();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void {{ ClassName }}::{{ UpperFirst(Property.attrib['Name']) }}Clear()
|
||||
@@ -562,12 +573,12 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re
|
||||
{%- if networkPropertyCount.update({'value': networkPropertyCount.value + 1}) %}{% endif -%}
|
||||
{% endcall %}
|
||||
{% if networkPropertyCount.value > 0 %}
|
||||
Multiplayer::MultiplayerStats& stats = Multiplayer::GetMultiplayer()->GetStats();
|
||||
[[maybe_unused]] Multiplayer::MultiplayerStats& stats = Multiplayer::GetMultiplayer()->GetStats();
|
||||
// We modify the record if we are writing an update so that we don't notify for a change that really didn't change the value (just a duplicated send from the server)
|
||||
[[maybe_unused]] bool modifyRecord = serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject;
|
||||
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
|
||||
{% if Property.attrib['Container'] != 'None' and Property.attrib['Container'] != 'Object' %}
|
||||
{ /* @todo Implement serialization for Vector and Array Network Properties
|
||||
{ // Serialization for Vector and Array Network Properties
|
||||
const uint32_t firstBit = static_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }});
|
||||
{% if Property.attrib['Container'] == 'Vector' %}
|
||||
const uint32_t lastBit = static_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }});
|
||||
@@ -575,17 +586,8 @@ bool {{ ClassName }}::Serialize{{ AutoComponentMacros.GetNetPropertiesSetName(Re
|
||||
const uint32_t lastBit = static_cast<uint32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'End') }});
|
||||
{% endif %}
|
||||
|
||||
AzNetworking::BitsetView deltaRecord(replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}, firstBit, lastBit - firstBit + 1);
|
||||
if (deltaRecord.AnySet())
|
||||
{
|
||||
{% if Property.attrib['Container'] == 'Vector' %}
|
||||
Multiplayer::SerializableFixedSizeVectorDeltaStruct<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}> deltaStruct(m_{{ LowerFirst(Property.attrib['Name']) }}, deltaRecord);
|
||||
{% else %}
|
||||
Multiplayer::SerializableFixedSizeArrayDeltaStruct<{% if Property.attrib['IsRewindable']|booleanTrue %}Multiplayer::RewindableObject<{% endif %}{{ Property.attrib['Type'] }}{% if Property.attrib['IsRewindable']|booleanTrue %}, Multiplayer::RewindHistorySize>{% endif %}, {{ Property.attrib['Count'] }}> deltaStruct(m_{{ Property.attrib['Name'] }}, deltaRecord);
|
||||
{% endif %}
|
||||
serializer.Serialize(deltaStruct, "{{ UpperFirst(Property.attrib['Name']) }}");
|
||||
}
|
||||
*/
|
||||
AzNetworking::FixedSizeBitsetView deltaRecord(replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}, firstBit, lastBit - firstBit + 1);
|
||||
m_{{ LowerFirst(Property.attrib['Name']) }}.Serialize(serializer, deltaRecord);
|
||||
}
|
||||
{% else %}
|
||||
Multiplayer::SerializeNetworkPropertyHelper
|
||||
@@ -615,7 +617,7 @@ void {{ ClassName }}::NotifyChanges{{ AutoComponentMacros.GetNetPropertiesSetNam
|
||||
{% call(Property) AutoComponentMacros.ParseNetworkProperties(Component, ReplicateFrom, ReplicateTo) %}
|
||||
{% if (Property.attrib['GenerateEventBindings']|booleanTrue) %}
|
||||
{% if Property.attrib['Container'] != 'None' and Property.attrib['Container'] != 'Object' %}
|
||||
/* todo Implement NotifyChangesAuthorityToClientProperties for Arrays and Vectors
|
||||
// NotifyChangesAuthorityToClientProperties for Arrays and Vectors
|
||||
for (uint32_t bitIndex = static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Start') }}), elementIndex = 0; bitIndex <= static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component, ReplicateFrom, ReplicateTo, Property, 'End') }}); ++bitIndex, ++elementIndex)
|
||||
{
|
||||
if (replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.GetBit(bitIndex){% if Property.attrib['Container'] == 'Vector' %} && elementIndex < m_{{ Property.attrib['Name'] }}.GetSize(){% endif %})
|
||||
@@ -627,7 +629,7 @@ void {{ ClassName }}::NotifyChanges{{ AutoComponentMacros.GetNetPropertiesSetNam
|
||||
if (replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.GetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property, 'Size') }})))
|
||||
{
|
||||
m_{{ LowerFirst(Property.attrib['Name']) }}SizeChangedEvent.Signal(m_{{ LowerFirst(Property.attrib['Name']) }}.size());
|
||||
} */
|
||||
}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
if (replicationRecord.m_{{ LowerFirst(AutoComponentMacros.GetNetPropertiesSetName(ReplicateFrom, ReplicateTo)) }}.GetBit(static_cast<int32_t>({{ AutoComponentMacros.GetNetPropertiesQualifiedPropertyDirtyEnum(Component.attrib['Name'], ReplicateFrom, ReplicateTo, Property) }})))
|
||||
@@ -645,7 +647,11 @@ void {{ ClassName }}::NotifyChanges{{ AutoComponentMacros.GetNetPropertiesSetNam
|
||||
{% macro DefineArchetypePropertyGet(Property, ClassType, ClassName, Prefix = '') %}
|
||||
{% if ClassType == '' or Property.attrib['ExportTo'] == ClassType or Property.attrib['ExportTo'] == "Common" %}
|
||||
{% if Property.attrib['Container'] == 'Array' %}
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
const RewindableArray<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Array() const
|
||||
{% else %}
|
||||
const AZStd::array<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Array() const
|
||||
{% endif %}
|
||||
{
|
||||
return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }};
|
||||
}
|
||||
@@ -656,7 +662,11 @@ const {{ Property.attrib['Type'] }}& {{ ClassName }}::Get{{ UpperFirst(Property.
|
||||
}
|
||||
|
||||
{% elif Property.attrib['Container'] == 'Vector' %}
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
const RewindableFixedVector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Vector() const
|
||||
{% else %}
|
||||
const AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }}>& {{ ClassName }}::Get{{ UpperFirst(Property.attrib['Name']) }}Vector() const
|
||||
{% endif %}
|
||||
{
|
||||
return {{ Prefix }}m_{{ LowerFirst(Property.attrib['Name']) }};
|
||||
}
|
||||
@@ -1472,7 +1482,14 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
{
|
||||
{% for Property in Component.iter('NetworkProperty') %}
|
||||
{% if Property.attrib['IsRewindable']|booleanTrue %}
|
||||
{% if Property.attrib['Container'] == 'Vector' or Property.attrib['Container'] == 'Array' %}
|
||||
for ( auto& element: m_{{ LowerFirst(Property.attrib['Name']) }})
|
||||
{
|
||||
element.SetOwningConnectionId(connectionId);
|
||||
}
|
||||
{% else %}
|
||||
m_{{ LowerFirst(Property.attrib['Name']) }}.SetOwningConnectionId(connectionId);
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<NetworkProperty Type="AZ::Quaternion" Name="rotation" Init="AZ::Quaternion::CreateIdentity()" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" 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="false" 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="false" GenerateEventBindings="true" />
|
||||
<NetworkProperty Type="float" Name="scale" Init="1.0f" ReplicateFrom="Authority" ReplicateTo="Client" IsRewindable="true" IsPredictable="true" IsPublic="true" Container="Object" ExposeToEditor="false" 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" />
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Multiplayer
|
||||
NetworkTransformComponent::NetworkTransformComponent()
|
||||
: m_rotationEventHandler([this](const AZ::Quaternion& rotation) { OnRotationChangedEvent(rotation); })
|
||||
, m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); })
|
||||
, m_scaleEventHandler([this](const AZ::Vector3& scale) { OnScaleChangedEvent(scale); })
|
||||
, m_scaleEventHandler([this](float scale) { OnScaleChangedEvent(scale); })
|
||||
, m_resetCountEventHandler([this](const uint8_t&) { OnResetCountChangedEvent(); })
|
||||
, m_entityPreRenderEventHandler([this](float deltaTime, float blendFactor) { OnPreRender(deltaTime, blendFactor); })
|
||||
{
|
||||
@@ -73,10 +73,10 @@ namespace Multiplayer
|
||||
m_targetTransform.SetTranslation(translation);
|
||||
}
|
||||
|
||||
void NetworkTransformComponent::OnScaleChangedEvent(const AZ::Vector3& scale)
|
||||
void NetworkTransformComponent::OnScaleChangedEvent(float scale)
|
||||
{
|
||||
m_previousTransform.SetScale(m_targetTransform.GetScale());
|
||||
m_targetTransform.SetScale(scale);
|
||||
m_previousTransform.SetUniformScale(m_targetTransform.GetUniformScale());
|
||||
m_targetTransform.SetUniformScale(scale);
|
||||
}
|
||||
|
||||
void NetworkTransformComponent::OnResetCountChangedEvent()
|
||||
@@ -119,6 +119,6 @@ namespace Multiplayer
|
||||
{
|
||||
SetRotation(worldTm.GetRotation());
|
||||
SetTranslation(worldTm.GetTranslation());
|
||||
SetScale(worldTm.GetScale());
|
||||
SetScale(worldTm.GetUniformScale());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 <Multiplayer/IMultiplayer.h>
|
||||
#include <Multiplayer/NetworkTime/RewindableArray.h>
|
||||
#include <Multiplayer/NetworkTime/RewindableFixedVector.h>
|
||||
#include <Multiplayer/NetworkTime/RewindableObject.h>
|
||||
#include <Source/NetworkTime/NetworkTime.h>
|
||||
#include <AzCore/Console/LoggerSystemComponent.h>
|
||||
#include <AzCore/Time/TimeSystemComponent.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class RewindableContainerTests
|
||||
: public AllocatorsFixture
|
||||
{
|
||||
public:
|
||||
Multiplayer::NetworkTime m_networkTime;
|
||||
AZ::LoggerSystemComponent m_loggerComponent;
|
||||
AZ::TimeSystemComponent m_timeComponent;
|
||||
};
|
||||
|
||||
static constexpr uint32_t RewindableContainerSize = 7;
|
||||
|
||||
TEST_F(RewindableContainerTests, BasicVectorTest)
|
||||
{
|
||||
Multiplayer::RewindableFixedVector<uint32_t, RewindableContainerSize> test(0, 0);
|
||||
|
||||
// Test push_back
|
||||
for (uint32_t idx = 0; idx < RewindableContainerSize; ++idx)
|
||||
{
|
||||
test.push_back(idx);
|
||||
EXPECT_EQ(idx, test[idx]);
|
||||
Multiplayer::GetNetworkTime()->IncrementHostFrameId();
|
||||
}
|
||||
|
||||
// Test rewind for all pushed values and overall size
|
||||
for (uint32_t idx = 0; idx < RewindableContainerSize; ++idx)
|
||||
{
|
||||
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(idx), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId);
|
||||
EXPECT_EQ(idx + 1, test.size());
|
||||
EXPECT_EQ(idx, test.back());
|
||||
}
|
||||
|
||||
// Test pop_back
|
||||
test.pop_back();
|
||||
EXPECT_EQ(RewindableContainerSize - 1, test.size());
|
||||
Multiplayer::GetNetworkTime()->IncrementHostFrameId();
|
||||
|
||||
// Test iterator
|
||||
uint32_t iterCount = 0;
|
||||
auto iter = test.begin();
|
||||
while (iter != test.end())
|
||||
{
|
||||
++iterCount;
|
||||
++iter;
|
||||
}
|
||||
EXPECT_EQ(RewindableContainerSize - 1, iterCount);
|
||||
|
||||
// Test clear and empty
|
||||
test.clear();
|
||||
EXPECT_EQ(0, test.size());
|
||||
Multiplayer::GetNetworkTime()->IncrementHostFrameId();
|
||||
EXPECT_TRUE(test.empty());
|
||||
|
||||
// Test rewind for pop_back and clear
|
||||
Multiplayer::ScopedAlterTime pop_time(static_cast<Multiplayer::HostFrameId>(RewindableContainerSize), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId);
|
||||
EXPECT_EQ(RewindableContainerSize - 1, test.size());
|
||||
Multiplayer::ScopedAlterTime clear_time(static_cast<Multiplayer::HostFrameId>(RewindableContainerSize + 1), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId);
|
||||
EXPECT_EQ(0, test.size());
|
||||
|
||||
// Test copy_values and resize_no_construct
|
||||
test.resize_no_construct(RewindableContainerSize);
|
||||
test.copy_values(&test[RewindableContainerSize-1], 1);
|
||||
EXPECT_EQ(1, test.size());
|
||||
test.resize_no_construct(RewindableContainerSize);
|
||||
EXPECT_EQ(test[0], test[RewindableContainerSize - 1]);
|
||||
}
|
||||
|
||||
TEST_F(RewindableContainerTests, BasicArrayTest)
|
||||
{
|
||||
Multiplayer::RewindableArray<uint32_t, RewindableContainerSize> test;
|
||||
|
||||
test.fill(0);
|
||||
Multiplayer::GetNetworkTime()->IncrementHostFrameId();
|
||||
// Test push_back
|
||||
for (uint32_t idx = 0; idx < RewindableContainerSize; ++idx)
|
||||
{
|
||||
test[idx] = idx;
|
||||
EXPECT_EQ(idx, test[idx].Get());
|
||||
Multiplayer::GetNetworkTime()->IncrementHostFrameId();
|
||||
}
|
||||
|
||||
// Test rewind for all values and overall size
|
||||
for (uint32_t idx = 1; idx <= RewindableContainerSize; ++idx)
|
||||
{
|
||||
Multiplayer::ScopedAlterTime time(static_cast<Multiplayer::HostFrameId>(idx), AZ::TimeMs{ 0 }, AzNetworking::InvalidConnectionId);
|
||||
for (uint32_t testIdx = 0; testIdx < RewindableContainerSize; ++testIdx)
|
||||
{
|
||||
if (testIdx < idx)
|
||||
{
|
||||
EXPECT_EQ(testIdx, test[testIdx].Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_EQ(0, test[testIdx].Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,10 @@ set(FILES
|
||||
Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h
|
||||
Include/Multiplayer/NetworkInput/NetworkInput.h
|
||||
Include/Multiplayer/NetworkTime/INetworkTime.h
|
||||
Include/Multiplayer/NetworkTime/RewindableArray.h
|
||||
Include/Multiplayer/NetworkTime/RewindableArray.inl
|
||||
Include/Multiplayer/NetworkTime/RewindableFixedVector.h
|
||||
Include/Multiplayer/NetworkTime/RewindableFixedVector.inl
|
||||
Include/Multiplayer/NetworkTime/RewindableObject.h
|
||||
Include/Multiplayer/NetworkTime/RewindableObject.inl
|
||||
Include/Multiplayer/ReplicationWindows/IReplicationWindow.h
|
||||
|
||||
@@ -13,5 +13,6 @@ set(FILES
|
||||
Tests/Main.cpp
|
||||
Tests/IMultiplayerConnectionMock.h
|
||||
Tests/MultiplayerSystemTests.cpp
|
||||
Tests/RewindableContainerTests.cpp
|
||||
Tests/RewindableObjectTests.cpp
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user