Add units for Rewindable containers and rework RewindableFixedVector to properly handle rewinding
This commit is contained in:
@@ -118,7 +118,7 @@ namespace Multiplayer
|
||||
constexpr iterator end() { return m_container.end(); }
|
||||
|
||||
private:
|
||||
AZStd::fixed_vector<RewindableObject<TYPE, Multiplayer::RewindHistorySize>, SIZE> m_container;
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace Multiplayer
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr RewindableFixedVector<TYPE, SIZE>::RewindableFixedVector(const TYPE& initialValue, uint32_t count)
|
||||
{
|
||||
m_container.resize(count, initialValue);
|
||||
m_rewindableSize = m_container.size();
|
||||
m_container.fill(initialValue);
|
||||
m_rewindableSize = count;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
@@ -30,15 +30,14 @@ namespace Multiplayer
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
bool RewindableFixedVector<TYPE, SIZE>::Serialize(AzNetworking::ISerializer& serializer)
|
||||
{
|
||||
m_rewindableSize = m_container.size();
|
||||
if(!m_rewindableSize.Serialize(serializer) && !resize(m_rewindableSize))
|
||||
if(!m_rewindableSize.Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < size(); ++i)
|
||||
for (uint32_t idx = 0; idx < size(); ++idx)
|
||||
{
|
||||
if(!m_container[i].Serialize(serializer))
|
||||
if(!m_container[idx].Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -53,8 +52,7 @@ namespace Multiplayer
|
||||
if (deltaRecord.GetBit(SIZE))
|
||||
{
|
||||
const uint32_t origSize = m_rewindableSize;
|
||||
m_rewindableSize = m_container.size();
|
||||
if(!m_rewindableSize.Serialize(serializer) && !resize(m_rewindableSize))
|
||||
if(!m_rewindableSize.Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -64,19 +62,19 @@ namespace Multiplayer
|
||||
deltaRecord.SetBit(SIZE, false);
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < size(); ++i)
|
||||
for (uint32_t idx = 0; idx < size(); ++idx)
|
||||
{
|
||||
if (deltaRecord.GetBit(i))
|
||||
if (deltaRecord.GetBit(idx))
|
||||
{
|
||||
serializer.ClearTrackedChangesFlag();
|
||||
if(!m_container[i].Serialize(serializer))
|
||||
if(!m_container[idx].Serialize(serializer))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((serializer.GetSerializerMode() == AzNetworking::SerializerMode::WriteToObject) && !serializer.GetTrackedChangesFlag())
|
||||
{
|
||||
deltaRecord.SetBit(i, false);
|
||||
deltaRecord.SetBit(idx, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,7 +90,7 @@ namespace Multiplayer
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t idx = 0; idx < bufferSize; ++i)
|
||||
for (uint32_t idx = 0; idx < bufferSize; ++idx)
|
||||
{
|
||||
m_container[idx] = buffer[idx];
|
||||
}
|
||||
@@ -104,9 +102,9 @@ namespace Multiplayer
|
||||
constexpr RewindableFixedVector<TYPE, SIZE>& RewindableFixedVector<TYPE, SIZE>::operator=(const RewindableFixedVector<TYPE, SIZE>& rhs)
|
||||
{
|
||||
resize(rhs.size());
|
||||
for (uint32_t idx = 0; idx < size(); ++i)
|
||||
for (uint32_t idx = 0; idx < size(); ++idx)
|
||||
{
|
||||
m_container[idx] = rhs.m_container[idx];
|
||||
m_container[idx] = rhs.m_container[idx].Get();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -136,8 +134,14 @@ namespace Multiplayer
|
||||
return true;
|
||||
}
|
||||
|
||||
m_container.resize(count, TYPE());
|
||||
m_rewindableSize = m_container.size();
|
||||
if (count > size())
|
||||
{
|
||||
for (uint32_t idx = size(); idx < count; ++idx)
|
||||
{
|
||||
m_container[idx] = TYPE();
|
||||
}
|
||||
}
|
||||
m_rewindableSize = count;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -150,8 +154,7 @@ namespace Multiplayer
|
||||
return false;
|
||||
}
|
||||
|
||||
m_container.resize_no_construct(count);
|
||||
m_rewindableSize = m_container.size();
|
||||
m_rewindableSize = count;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -159,8 +162,11 @@ namespace Multiplayer
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr void RewindableFixedVector<TYPE, SIZE>::clear()
|
||||
{
|
||||
m_container.clear();
|
||||
m_rewindableSize = m_container.size();
|
||||
for (uint32_t idx = 0; idx < SIZE; ++idx)
|
||||
{
|
||||
m_container[idx] = TYPE();
|
||||
}
|
||||
m_rewindableSize = 0;
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
@@ -182,8 +188,8 @@ namespace Multiplayer
|
||||
{
|
||||
if (size() < SIZE)
|
||||
{
|
||||
m_container.push_back(value);
|
||||
m_rewindableSize = m_container.size();
|
||||
m_container[m_rewindableSize] = value;
|
||||
m_rewindableSize = m_rewindableSize + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -195,8 +201,8 @@ namespace Multiplayer
|
||||
{
|
||||
if (size() > 0)
|
||||
{
|
||||
m_container.pop_back();
|
||||
m_rewindableSize = m_container.size();
|
||||
m_rewindableSize = m_rewindableSize - 1;
|
||||
m_container[m_rewindableSize] = TYPE();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -206,14 +212,14 @@ namespace Multiplayer
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
constexpr bool RewindableFixedVector<TYPE, SIZE>::empty() const
|
||||
{
|
||||
return m_container.empty();
|
||||
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.back().Get();
|
||||
return m_container[m_rewindableSize - 1].Get();
|
||||
}
|
||||
|
||||
template <typename TYPE, uint32_t SIZE>
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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;
|
||||
static constexpr uint32_t RewindableBufferFrames = 32;
|
||||
|
||||
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 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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