Files
UnrealEngine/Engine/Plugins/Runtime/ReplicationSystemTestPlugin/Source/Private/Tests/Serialization/TestInstancedStructNetSerializer.cpp
2025-05-18 13:04:45 +08:00

1176 lines
46 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Tests/Serialization/TestInstancedStructNetSerializer.h"
#include "Tests/Serialization/TestNetSerializerFixture.h"
#include "Tests/ReplicationSystem/ReplicationSystemServerClientTestFixture.h"
#include "Iris/ReplicationSystem/ReplicationFragmentUtil.h"
#include "Iris/ReplicationSystem/ReplicationSystemInternal.h"
#include "Iris/ReplicationState/PropertyNetSerializerInfoRegistry.h"
#include "Iris/ReplicationState/ReplicationStateDescriptorBuilder.h"
#include "Iris/Serialization/InternalNetSerializationContext.h"
#include "Iris/Serialization/NetReferenceCollector.h"
#include "Iris/Serialization/NetSerializers.h"
#include "Net/UnrealNetwork.h"
namespace UE::Net
{
FTestMessage& operator<<(FTestMessage& Message, const FInstancedStruct& InstancedStruct)
{
FString String;
InstancedStruct.ExportTextItem(String, FInstancedStruct(), nullptr, 0, nullptr);
return Message << String;
}
struct FStructForInstancedStructTestWithCustomApplyNetSerializer
{
// Version
static const uint32 Version = 0;
// Types
typedef FStructForInstancedStructTestWithCustomApply SourceType;
typedef int QuantizedType;
typedef FNetSerializerConfig ConfigType;
inline static const ConfigType DefaultConfig;
//
static void Serialize(FNetSerializationContext&, const FNetSerializeArgs&);
static void Deserialize(FNetSerializationContext&, const FNetDeserializeArgs&);
static void Quantize(FNetSerializationContext&, const FNetQuantizeArgs&);
static void Dequantize(FNetSerializationContext&, const FNetDequantizeArgs&);
static bool IsEqual(FNetSerializationContext&, const FNetIsEqualArgs&);
static void Apply(FNetSerializationContext&, const FNetApplyArgs&);
private:
class FNetSerializerRegistryDelegates final : private UE::Net::FNetSerializerRegistryDelegates
{
public:
virtual ~FNetSerializerRegistryDelegates();
private:
virtual void OnPreFreezeNetSerializerRegistry() override;
inline static const FName StructForInstancedStructTestWithCustomApplyNetSerializer = FName("StructForInstancedStructTestWithCustomApply");
UE_NET_IMPLEMENT_NAMED_STRUCT_NETSERIALIZER_INFO(StructForInstancedStructTestWithCustomApplyNetSerializer, FStructForInstancedStructTestWithCustomApplyNetSerializer);
};
inline static FStructForInstancedStructTestWithCustomApplyNetSerializer::FNetSerializerRegistryDelegates NetSerializerRegistryDelegates;
};
UE_NET_IMPLEMENT_SERIALIZER(FStructForInstancedStructTestWithCustomApplyNetSerializer);
struct FStructForInstancedStructTestWithCustomSerializerNetSerializer
{
// Version
static const uint32 Version = 0;
// Types
typedef FStructForInstancedStructTestWithCustomSerializer SourceType;
typedef int QuantizedType;
typedef FNetSerializerConfig ConfigType;
inline static const ConfigType DefaultConfig;
//
static void Serialize(FNetSerializationContext&, const FNetSerializeArgs&);
static void Deserialize(FNetSerializationContext&, const FNetDeserializeArgs&);
static void Quantize(FNetSerializationContext&, const FNetQuantizeArgs&);
static void Dequantize(FNetSerializationContext&, const FNetDequantizeArgs&);
static bool IsEqual(FNetSerializationContext&, const FNetIsEqualArgs&);
private:
class FNetSerializerRegistryDelegates final : private UE::Net::FNetSerializerRegistryDelegates
{
public:
virtual ~FNetSerializerRegistryDelegates();
private:
virtual void OnPreFreezeNetSerializerRegistry() override;
inline static const FName StructForInstancedStructTestWithCustomSerializerNetSerializer = FName("StructForInstancedStructTestWithCustomSerializer");
UE_NET_IMPLEMENT_NAMED_STRUCT_NETSERIALIZER_INFO(StructForInstancedStructTestWithCustomSerializerNetSerializer, FStructForInstancedStructTestWithCustomSerializerNetSerializer);
};
inline static FStructForInstancedStructTestWithCustomSerializerNetSerializer::FNetSerializerRegistryDelegates NetSerializerRegistryDelegates;
};
UE_NET_IMPLEMENT_SERIALIZER(FStructForInstancedStructTestWithCustomSerializerNetSerializer);
}
namespace UE::Net::Private
{
FTestMessage& PrintInstancedStructNetSerializerConfig(FTestMessage& Message, const FNetSerializerConfig& InConfig)
{
const FInstancedStructNetSerializerConfig& Config = static_cast<const FInstancedStructNetSerializerConfig&>(InConfig);
for (const auto& SupportedType : Config.SupportedTypes)
{
Message << SupportedType.Get()->GetFullName();
}
return Message;
}
class FTestInstancedStructNetSerializerFixture : public FReplicationSystemServerClientTestFixture
{
public:
FTestInstancedStructNetSerializerFixture() : FReplicationSystemServerClientTestFixture() {}
protected:
virtual void SetUp() override;
virtual void TearDown() override;
// Composable operations for testing the serializer
void Serialize();
void Deserialize();
void SerializeDelta();
void DeserializeDelta();
void Quantize();
void QuantizeTwoStates();
void Dequantize();
bool IsEqual(bool bQuantized);
void Clone();
void Validate();
void FreeQuantizedState();
// Instantiates a struct with a modified property on InstancedStruct0
void SetNonDefaultInstanceState();
// Adds multiple elements, at least one uninitialized and at least two initialized with at least one modified property, to InstancedStructArray0
void SetNonDefaultArrayState();
bool AreEqual(const FInstancedStruct* Value0, const FInstancedStruct* Value1);
const FNetSerializer* GetInstancedStructNetSerializer(bool bIsArray) const;
const FNetSerializerConfig* GetInstancedStructNetSerializerConfig(bool bIsArray) const;
protected:
FNetSerializationContext NetSerializationContext;
FInternalNetSerializationContext InternalNetSerializationContext;
FInstancedStruct InstancedStruct0;
FInstancedStruct InstancedStruct1;
TArray<FInstancedStruct> InstancedStructArray0;
TArray<FInstancedStruct> InstancedStructArray1;
FStructNetSerializerConfig InstancedStructNetSerializerConfig;
FStructNetSerializerConfig InstancedStructArrayNetSerializerConfig;
alignas(16) uint8 QuantizedBuffer[2][128];
alignas(16) uint8 ClonedQuantizedBuffer[2][128];
alignas(16) uint8 BitStreamBuffer[2048];
bool bHasQuantizedState = false;
bool bHasClonedQuantizedState = false;
bool bIsTestingArray = false;
uint32 QuantizedStateCount = 0;
uint32 ClonedQuantizedStateCount = 0;
FNetBitStreamWriter Writer;
FNetBitStreamReader Reader;
};
}
namespace UE::Net::Private
{
// Instance tests
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestQuantizeUninitialized)
{
Quantize();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestQuantizeInitialized)
{
SetNonDefaultInstanceState();
Quantize();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDequantizeUninitialized)
{
Quantize();
Dequantize();
UE_NET_ASSERT_EQ(InstancedStruct0, InstancedStruct1);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDequantizeInitialized)
{
SetNonDefaultInstanceState();
Quantize();
Dequantize();
UE_NET_ASSERT_EQ(InstancedStruct0, InstancedStruct1);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestSerializeUninitialized)
{
Quantize();
Serialize();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestSerializeInitialized)
{
SetNonDefaultInstanceState();
Quantize();
Serialize();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDeserializeUninitialized)
{
Quantize();
Serialize();
FreeQuantizedState();
Deserialize();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDeserializeInitialized)
{
SetNonDefaultInstanceState();
Quantize();
Serialize();
FreeQuantizedState();
Deserialize();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDequantizeSerializedUninitializedState)
{
Quantize();
Serialize();
FreeQuantizedState();
Deserialize();
Dequantize();
UE_NET_ASSERT_EQ(InstancedStruct0, InstancedStruct1);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDequantizeSerializedInitializedState)
{
SetNonDefaultInstanceState();
Quantize();
Serialize();
FreeQuantizedState();
Deserialize();
Dequantize();
UE_NET_ASSERT_EQ(InstancedStruct0, InstancedStruct1);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestSerializeDeltaEqualStates)
{
QuantizeTwoStates();
SerializeDelta();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestSerializeDeltaNonEqualStates)
{
SetNonDefaultInstanceState();
QuantizeTwoStates();
SerializeDelta();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDeserializeDeltaEqualStates)
{
QuantizeTwoStates();
SerializeDelta();
DeserializeDelta();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDeserializeDeltaNonEqualStates)
{
SetNonDefaultInstanceState();
QuantizeTwoStates();
SerializeDelta();
DeserializeDelta();
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDequantizeDeltaSerializedState)
{
SetNonDefaultInstanceState();
QuantizeTwoStates();
SerializeDelta();
DeserializeDelta();
Dequantize();
UE_NET_ASSERT_EQ(InstancedStruct0, InstancedStruct1);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestCollectReferencesUninitialized)
{
Quantize();
FNetReferenceCollector Collector;
FNetCollectReferencesArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Source = NetSerializerValuePointer(&QuantizedBuffer[0]);
Args.Collector = NetSerializerValuePointer(&Collector);
GetInstancedStructNetSerializer(bIsTestingArray)->CollectNetReferences(NetSerializationContext, Args);
UE_NET_ASSERT_EQ(Collector.GetCollectedReferences().Num(), 0);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestCollectReferencesStructNoRef)
{
InstancedStruct0.InitializeAs<FStructForInstancedStructTestD>();
Quantize();
FNetReferenceCollector Collector(ENetReferenceCollectorTraits::IncludeInvalidReferences);
FNetCollectReferencesArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Source = NetSerializerValuePointer(&QuantizedBuffer[0]);
Args.Collector = NetSerializerValuePointer(&Collector);
GetInstancedStructNetSerializer(bIsTestingArray)->CollectNetReferences(NetSerializationContext, Args);
UE_NET_ASSERT_EQ(Collector.GetCollectedReferences().Num(), 1);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestCollectReferencesStructWithRef)
{
InstancedStruct0.InitializeAs<FStructForInstancedStructTestWithObjectReference>();
InstancedStruct0.GetMutable<FStructForInstancedStructTestWithObjectReference>().SomeObject = FStructForInstancedStructTestWithObjectReference::StaticStruct();
Quantize();
FNetReferenceCollector Collector(ENetReferenceCollectorTraits::IncludeInvalidReferences);
FNetCollectReferencesArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Source = NetSerializerValuePointer(&QuantizedBuffer[0]);
Args.Collector = NetSerializerValuePointer(&Collector);
GetInstancedStructNetSerializer(bIsTestingArray)->CollectNetReferences(NetSerializationContext, Args);
UE_NET_ASSERT_GE(Collector.GetCollectedReferences().Num(), 2);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestIsEqualExternal)
{
constexpr bool bUseQuantizedState = false;
// Default state compared to default state
InstancedStruct0.Reset();
InstancedStruct1.Reset();
UE_NET_ASSERT_TRUE(IsEqual(bUseQuantizedState));
// Non-default state compared to default state
SetNonDefaultInstanceState();
UE_NET_ASSERT_FALSE(IsEqual(bUseQuantizedState));
// Non-default state compared to non-default state
InstancedStruct1 = InstancedStruct0;
UE_NET_ASSERT_TRUE(IsEqual(bUseQuantizedState));
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestIsEqualQuantized)
{
constexpr bool bUseQuantizedState = true;
// Default state compared to default state
InstancedStruct0.Reset();
Quantize();
Clone();
UE_NET_ASSERT_TRUE(IsEqual(bUseQuantizedState));
// Non-default state compared to default state
SetNonDefaultInstanceState();
Quantize();
UE_NET_ASSERT_FALSE(IsEqual(bUseQuantizedState));
// Non-default state compared to non-default state
Clone();
UE_NET_ASSERT_TRUE(IsEqual(bUseQuantizedState));
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestValidate)
{
Validate();
}
// Array tests. There's no custom FInstancedStructArrayNetSerializer so we just add the one test until we require in-depth testing.
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, TestDequantizeSerializedInitializedArrayState)
{
bIsTestingArray = true;
SetNonDefaultArrayState();
Quantize();
Serialize();
FreeQuantizedState();
Deserialize();
Dequantize();
UE_NET_ASSERT_TRUE(InstancedStruct0 == InstancedStruct1);
}
// End-to-end tests
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, ModifyInstance)
{
// Add a client
FReplicationSystemTestClient* Client = CreateClient();
// Spawn object on server
UInstancedStructNetSerializerTestObject* ServerObject = Server->CreateObject<UInstancedStructNetSerializerTestObject>();
ServerObject->InstancedStruct.InitializeAs<FStructForInstancedStructTestB>();
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestB>().SomeFloat = 12.0f;
// Replicate
Server->UpdateAndSend({ Client });
auto ClientObject = Client->GetObjectAs<UInstancedStructNetSerializerTestObject>(ServerObject->NetRefHandle);
UE_NET_ASSERT_NE(ClientObject, nullptr);
CA_ASSUME(ClientObject != nullptr);
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct, ServerObject->InstancedStruct);
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestB>().SomeFloat, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestB>().SomeFloat);
// Modify
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestB>().SomeFloat += 1.0f;
// Replicate
Server->UpdateAndSend({ Client });
// Verify that we detected the modification
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestB>().SomeFloat, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestB>().SomeFloat);
// Switch type
ServerObject->InstancedStruct.InitializeAs<FStructForInstancedStructTestA>();
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestA>().SomeUint16 = 100;
// Replicate
Server->UpdateAndSend({ Client });
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct, ServerObject->InstancedStruct);
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestA>().SomeUint16, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestA>().SomeUint16);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, ModifyArray)
{
// Add a client
FReplicationSystemTestClient* Client = CreateClient();
// Spawn objects on server
UInstancedStructNetSerializerTestObject* ServerObject = Server->CreateObject<UInstancedStructNetSerializerTestObject>();
// Add entries to the array
ServerObject->InstancedStructArray.Add(FInstancedStruct::Make<FStructForInstancedStructTestA>());
ServerObject->InstancedStructArray.Add(FInstancedStruct::Make<FStructForInstancedStructTestB>());
ServerObject->InstancedStructArray.Add(FInstancedStruct::Make<FStructForInstancedStructTestC>());
ServerObject->InstancedStructArray.Add(FInstancedStruct::Make<FStructForInstancedStructTestD>());
ServerObject->InstancedStructArray[1].GetMutable<FStructForInstancedStructTestB>().SomeFloat = 13.0f;
// Replicate
Server->UpdateAndSend({ Client });
auto ClientObject = Client->GetObjectAs<UInstancedStructNetSerializerTestObject>(ServerObject->NetRefHandle);
UE_NET_ASSERT_NE(ClientObject, nullptr);
CA_ASSUME(ClientObject != nullptr);
UE_NET_ASSERT_EQ(ClientObject->InstancedStructArray.Num(), ServerObject->InstancedStructArray.Num());
UE_NET_ASSERT_EQ(ClientObject->InstancedStructArray[1].Get<FStructForInstancedStructTestB>().SomeFloat, 13.0f);
// Modify value and see that it is replicated as expected
ServerObject->InstancedStructArray[1].GetMutable<FStructForInstancedStructTestB>().SomeFloat += 2.0f;
// Replicate
Server->UpdateAndSend({ Client });
// Verified that the client got the modified value
UE_NET_ASSERT_EQ(ClientObject->InstancedStructArray[1].Get<FStructForInstancedStructTestB>().SomeFloat, ServerObject->InstancedStructArray[1].Get<FStructForInstancedStructTestB>().SomeFloat);
// Switch type
ServerObject->InstancedStructArray[2].InitializeAs<FStructForInstancedStructTestA>();
ServerObject->InstancedStructArray[2].GetMutable<FStructForInstancedStructTestA>().SomeUint16 += 1;
// Replicate
Server->UpdateAndSend({ Client });
// Verified that the client got the modified value
UE_NET_ASSERT_EQ(ClientObject->InstancedStructArray[2], ClientObject->InstancedStructArray[2]);
UE_NET_ASSERT_EQ(ClientObject->InstancedStructArray[2].Get<FStructForInstancedStructTestA>().SomeUint16, ServerObject->InstancedStructArray[2].Get<FStructForInstancedStructTestA>().SomeUint16);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, NonReplicatedPropertiesAreNotClobbered)
{
// Add a client
FReplicationSystemTestClient* Client = CreateClient();
// Spawn objects on server
UInstancedStructNetSerializerTestObject* ServerObject = Server->CreateObject<UInstancedStructNetSerializerTestObject>();
// Initialize struct with some non-replicated properties.
ServerObject->InstancedStruct.InitializeAs<FStructForInstancedStructTestWithNonReplicatedProperties>();
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA = 1333;
// Replicate
Server->UpdateAndSend({ Client });
UInstancedStructNetSerializerTestObject* ClientObject = Client->GetObjectAs<UInstancedStructNetSerializerTestObject>(ServerObject->NetRefHandle);
UE_NET_ASSERT_NE(ClientObject, nullptr);
CA_ASSUME(ClientObject != nullptr);
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA);
// Modify value and verify that it's replicated as expected
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA = 1337;
// Modify non-replicated property on the client
ClientObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithNonReplicatedProperties>().IntB = 1331;
// Replicate
Server->UpdateAndSend({ Client });
// Verified that the client got the modified value
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA);
// Verified that the non-replicated property remained unchanged on the client
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntB, 1331);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, NetSerializerApplyIsCalled)
{
// Add a client
FReplicationSystemTestClient* Client = CreateClient();
// Spawn objects on server
UInstancedStructNetSerializerTestObject* ServerObject = Server->CreateObject<UInstancedStructNetSerializerTestObject>();
// Initialize struct with custom apply.
ServerObject->InstancedStruct.InitializeAs<FStructForInstancedStructTestWithCustomApply>();
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithCustomApply>().Uint = 1333;
// Replicate
Server->UpdateAndSend({ Client });
UInstancedStructNetSerializerTestObject* ClientObject = Client->GetObjectAs<UInstancedStructNetSerializerTestObject>(ServerObject->NetRefHandle);
UE_NET_ASSERT_NE(ClientObject, nullptr);
CA_ASSUME(ClientObject != nullptr);
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomApply>().Uint, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomApply>().Uint);
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomApply>().ApplyCallCount, 1U);
// Modify value and verify that it's replicated as expected
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithCustomApply>().Uint = 1337;
// Modify Apply handled property and verify that it doesn't overwrite the client value
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithCustomApply>().ApplyCallCount = 1337;
// Replicate
Server->UpdateAndSend({ Client });
// Verified that the client got the modified value
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomApply>().Uint, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomApply>().Uint);
// Verified that the custom handled property in Apply is as expected
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomApply>().ApplyCallCount, 2U);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, CustomSerializedStructIsOverwritten)
{
// Add a client
FReplicationSystemTestClient* Client = CreateClient();
// Spawn objects on server
UInstancedStructNetSerializerTestObject* ServerObject = Server->CreateObject<UInstancedStructNetSerializerTestObject>();
// Initialize struct with custom serializer.
ServerObject->InstancedStruct.InitializeAs<FStructForInstancedStructTestWithCustomSerializer>();
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithCustomSerializer>().Uint = 1333;
// Replicate
Server->UpdateAndSend({ Client });
UInstancedStructNetSerializerTestObject* ClientObject = Client->GetObjectAs<UInstancedStructNetSerializerTestObject>(ServerObject->NetRefHandle);
UE_NET_ASSERT_NE(ClientObject, nullptr);
CA_ASSUME(ClientObject != nullptr);
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomSerializer>().Uint, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomSerializer>().Uint);
// Modify value and verify that it's replicated as expected
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithCustomSerializer>().Uint = 1337;
// Modify not replicated client values and verify they're overwritten since it's a custom serializer without apply
ClientObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithCustomSerializer>().NotReplicatedUint = 1338;
ClientObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithCustomSerializer>().NotPropertyUint = 1339;
// Replicate
Server->UpdateAndSend({ Client });
// Verified that the client got the modified value
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomSerializer>().Uint, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomSerializer>().Uint);
// Verified that the not replicated properties did get overwritten
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomSerializer>().NotReplicatedUint, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomSerializer>().NotReplicatedUint);
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomSerializer>().NotPropertyUint, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestWithCustomSerializer>().NotPropertyUint);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, NotFullyReplicatedStructIsAppliedCorrectly)
{
// Add a client
FReplicationSystemTestClient* Client = CreateClient();
// Spawn objects on server
UInstancedStructNetSerializerTestObject* ServerObject = Server->CreateObject<UInstancedStructNetSerializerTestObject>();
// Initialize with a not fully replicated struct
ServerObject->InstancedStruct.InitializeAs<FStructForInstancedStructTestWithNonReplicatedProperties>();
// Replicate
Server->UpdateAndSend({ Client });
UInstancedStructNetSerializerTestObject* ClientObject = Client->GetObjectAs<UInstancedStructNetSerializerTestObject>(ServerObject->NetRefHandle);
// Modify not replicated value on the client
ClientObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithNonReplicatedProperties>().IntB = 1337;
// Modify value on server to trigger replication and apply of the struct
ServerObject->InstancedStruct.GetMutable<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA += 1;
// Replicate
Server->UpdateAndSend({ Client });
// Verified that the client got the modified value
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA, ServerObject->InstancedStruct.Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA);
// Verify the not replicated value remained as previously set
UE_NET_ASSERT_EQ(ClientObject->InstancedStruct.Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntB, 1337);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, NotFullyReplicatedStructInArrayIsAppliedCorrectly)
{
// Add a client
FReplicationSystemTestClient* Client = CreateClient();
// Spawn objects on server
UInstancedStructNetSerializerTestObject* ServerObject = Server->CreateObject<UInstancedStructNetSerializerTestObject>();
// Initialize an array entry with a not fully replicated struct
ServerObject->InstancedStructArray.Add(FInstancedStruct::Make<FStructForInstancedStructTestWithNonReplicatedProperties>());
// Replicate
Server->UpdateAndSend({ Client });
UInstancedStructNetSerializerTestObject* ClientObject = Client->GetObjectAs<UInstancedStructNetSerializerTestObject>(ServerObject->NetRefHandle);
// Modify not replicated value on the client
ClientObject->InstancedStructArray[0].GetMutable<FStructForInstancedStructTestWithNonReplicatedProperties>().IntB = 1337;
// Modify value on server to trigger replication and apply of the struct
ServerObject->InstancedStructArray[0].GetMutable<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA += 1;
// Replicate
Server->UpdateAndSend({ Client });
// Verified that the client got the modified value
UE_NET_ASSERT_EQ(ClientObject->InstancedStructArray[0].Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA, ServerObject->InstancedStructArray[0].Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA);
// Verify the not replicated value remained as previously set
UE_NET_ASSERT_EQ(ClientObject->InstancedStructArray[0].Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntB, 1337);
}
UE_NET_TEST_FIXTURE(FTestInstancedStructNetSerializerFixture, NotFullyReplicatedStructInArrayInStructIsAppliedCorrectly)
{
// Add a client
FReplicationSystemTestClient* Client = CreateClient();
// Spawn objects on server
UInstancedStructNetSerializerTestObject* ServerObject = Server->CreateObject<UInstancedStructNetSerializerTestObject>();
// Initialize an array entry with a not fully replicated struct
ServerObject->StructWithInstancedStructArray.InstancedStructArray.Add(FInstancedStruct::Make<FStructForInstancedStructTestWithNonReplicatedProperties>());
// Replicate
Server->UpdateAndSend({ Client });
UInstancedStructNetSerializerTestObject* ClientObject = Client->GetObjectAs<UInstancedStructNetSerializerTestObject>(ServerObject->NetRefHandle);
// Modify not replicated value on the client
ClientObject->StructWithInstancedStructArray.InstancedStructArray[0].GetMutable<FStructForInstancedStructTestWithNonReplicatedProperties>().IntB = 1337;
// Modify value on server to trigger replication and apply of the struct
ServerObject->StructWithInstancedStructArray.InstancedStructArray[0].GetMutable<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA += 1;
// Replicate
Server->UpdateAndSend({ Client });
// Verified that the client got the modified value
UE_NET_ASSERT_EQ(ClientObject->StructWithInstancedStructArray.InstancedStructArray[0].Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA, ServerObject->StructWithInstancedStructArray.InstancedStructArray[0].Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntA);
// Verify the not replicated value remained as previously set
UE_NET_ASSERT_EQ(ClientObject->StructWithInstancedStructArray.InstancedStructArray[0].Get<FStructForInstancedStructTestWithNonReplicatedProperties>().IntB, 1337);
}
// Fixture implementation
void FTestInstancedStructNetSerializerFixture::SetUp()
{
FReplicationSystemServerClientTestFixture::SetUp();
// Init default serialization context
InternalNetSerializationContext.ReplicationSystem = Server->ReplicationSystem;
FInternalNetSerializationContext TempInternalNetSerializationContext;
FInternalNetSerializationContext::FInitParameters TempInternalNetSerializationContextInitParams;
TempInternalNetSerializationContextInitParams.ReplicationSystem = Server->ReplicationSystem;
TempInternalNetSerializationContextInitParams.ObjectResolveContext.RemoteNetTokenStoreState = Server->ReplicationSystem->GetNetTokenStore()->GetLocalNetTokenStoreState();
TempInternalNetSerializationContext.Init(TempInternalNetSerializationContextInitParams);
InternalNetSerializationContext = MoveTemp(TempInternalNetSerializationContext);
NetSerializationContext.SetInternalContext(&InternalNetSerializationContext);
FMemory::Memzero(QuantizedBuffer, sizeof(QuantizedBuffer));
bHasQuantizedState = false;
bHasClonedQuantizedState = false;
if (!InstancedStructNetSerializerConfig.StateDescriptor.IsValid())
{
FReplicationStateDescriptorBuilder::FParameters Params;
InstancedStructNetSerializerConfig.StateDescriptor = FReplicationStateDescriptorBuilder::CreateDescriptorForStruct(FTestInstancedStruct::StaticStruct(), Params);
}
if (!InstancedStructArrayNetSerializerConfig.StateDescriptor.IsValid())
{
FReplicationStateDescriptorBuilder::FParameters Params;
InstancedStructArrayNetSerializerConfig.StateDescriptor = FReplicationStateDescriptorBuilder::CreateDescriptorForStruct(FTestInstancedStructArray::StaticStruct(), Params);
}
}
void FTestInstancedStructNetSerializerFixture::TearDown()
{
InstancedStruct0.Reset();
InstancedStruct1.Reset();
InstancedStructArray0.Reset();
InstancedStructArray1.Reset();
FreeQuantizedState();
FReplicationSystemServerClientTestFixture::TearDown();
}
void FTestInstancedStructNetSerializerFixture::Serialize()
{
// Must have run quantize before this
UE_NET_ASSERT_TRUE(bHasQuantizedState);
// Serialize data
Writer.InitBytes(BitStreamBuffer, sizeof(BitStreamBuffer));
FNetSerializationContext Context(&Writer);
Context.SetInternalContext(NetSerializationContext.GetInternalContext());
FNetSerializeArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Source = NetSerializerValuePointer(&QuantizedBuffer[0]);
GetInstancedStructNetSerializer(bIsTestingArray)->Serialize(Context, Args);
Writer.CommitWrites();
UE_NET_ASSERT_FALSE(Context.HasError());
UE_NET_ASSERT_GT(Writer.GetPosBits(), 0U);
}
void FTestInstancedStructNetSerializerFixture::Deserialize()
{
// Check pre-conditions
UE_NET_ASSERT_FALSE(bHasQuantizedState);
UE_NET_ASSERT_GT(Writer.GetPosBytes(), 0U);
Reader.InitBits(BitStreamBuffer, Writer.GetPosBits());
FNetSerializationContext Context(&Reader);
Context.SetInternalContext(NetSerializationContext.GetInternalContext());
FNetDeserializeArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Target = NetSerializerValuePointer(&QuantizedBuffer[0]);
GetInstancedStructNetSerializer(bIsTestingArray)->Deserialize(Context, Args);
bHasQuantizedState = true;
UE_NET_ASSERT_FALSE(Context.HasErrorOrOverflow());
UE_NET_ASSERT_GT(Reader.GetPosBits(), 0U);
}
void FTestInstancedStructNetSerializerFixture::SerializeDelta()
{
// Check pre-conditions
UE_NET_ASSERT_TRUE(bHasQuantizedState);
UE_NET_ASSERT_EQ(QuantizedStateCount, 2U);
// Serialize data
Writer.InitBytes(BitStreamBuffer, sizeof(BitStreamBuffer));
FNetSerializationContext Context(&Writer);
Context.SetInternalContext(NetSerializationContext.GetInternalContext());
FNetSerializeDeltaArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Source = NetSerializerValuePointer(&QuantizedBuffer[0]);
Args.Prev = NetSerializerValuePointer(&QuantizedBuffer[1]);
GetInstancedStructNetSerializer(bIsTestingArray)->SerializeDelta(Context, Args);
Writer.CommitWrites();
UE_NET_ASSERT_FALSE(Context.HasErrorOrOverflow());
UE_NET_ASSERT_GT(Writer.GetPosBits(), 0U);
}
void FTestInstancedStructNetSerializerFixture::DeserializeDelta()
{
// Check pre-conditions
UE_NET_ASSERT_GT(Writer.GetPosBytes(), 0U);
Reader.InitBits(BitStreamBuffer, Writer.GetPosBits());
FNetSerializationContext Context(&Reader);
Context.SetInternalContext(NetSerializationContext.GetInternalContext());
FNetDeserializeDeltaArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Target = NetSerializerValuePointer(&QuantizedBuffer[0]);
Args.Prev = NetSerializerValuePointer(&QuantizedBuffer[1]);
GetInstancedStructNetSerializer(bIsTestingArray)->DeserializeDelta(Context, Args);
bHasQuantizedState = true;
QuantizedStateCount = 1;
UE_NET_ASSERT_FALSE(Context.HasErrorOrOverflow());
UE_NET_ASSERT_GT(Reader.GetPosBits(), 0U);
}
void FTestInstancedStructNetSerializerFixture::Quantize()
{
FNetQuantizeArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Target = NetSerializerValuePointer(&QuantizedBuffer[0]);
Args.Source = bIsTestingArray ? NetSerializerValuePointer(&InstancedStructArray0) : NetSerializerValuePointer(&InstancedStruct0);
GetInstancedStructNetSerializer(bIsTestingArray)->Quantize(NetSerializationContext, Args);
bHasQuantizedState = true;
QuantizedStateCount = 1;
UE_NET_ASSERT_FALSE(NetSerializationContext.HasError());
}
void FTestInstancedStructNetSerializerFixture::QuantizeTwoStates()
{
Quantize();
FNetQuantizeArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Target = NetSerializerValuePointer(&QuantizedBuffer[1]);
Args.Source = bIsTestingArray ? NetSerializerValuePointer(&InstancedStructArray1) : NetSerializerValuePointer(&InstancedStruct1);
GetInstancedStructNetSerializer(bIsTestingArray)->Quantize(NetSerializationContext, Args);
bHasQuantizedState = true;
QuantizedStateCount = 2;
UE_NET_ASSERT_FALSE(NetSerializationContext.HasError());
}
void FTestInstancedStructNetSerializerFixture::Clone()
{
// Check pre-conditions
UE_NET_ASSERT_TRUE(bHasQuantizedState);
FMemory::Memcpy(ClonedQuantizedBuffer[0], QuantizedBuffer[0], sizeof(QuantizedBuffer[0]));
FNetCloneDynamicStateArgs Args = {};
Args.Source = NetSerializerValuePointer(&QuantizedBuffer[0]);
Args.Target = NetSerializerValuePointer(&ClonedQuantizedBuffer[0]);
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
GetInstancedStructNetSerializer(bIsTestingArray)->CloneDynamicState(NetSerializationContext, Args);
bHasClonedQuantizedState = true;
ClonedQuantizedStateCount = 1;
}
void FTestInstancedStructNetSerializerFixture::FreeQuantizedState()
{
FNetFreeDynamicStateArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
if (bHasQuantizedState)
{
for (uint32 StateIt = 0, StateEndIt = QuantizedStateCount; StateIt != StateEndIt; ++StateIt)
{
Args.Source = NetSerializerValuePointer(&QuantizedBuffer[StateIt]);
GetInstancedStructNetSerializer(bIsTestingArray)->FreeDynamicState(NetSerializationContext, Args);
FMemory::Memzero(&QuantizedBuffer[StateIt], sizeof(QuantizedBuffer[StateIt]));
}
bHasQuantizedState = false;
}
if (bHasClonedQuantizedState)
{
for (uint32 StateIt = 0, StateEndIt = ClonedQuantizedStateCount; StateIt != StateEndIt; ++StateIt)
{
Args.Source = NetSerializerValuePointer(&ClonedQuantizedBuffer[StateIt]);
GetInstancedStructNetSerializer(bIsTestingArray)->FreeDynamicState(NetSerializationContext, Args);
FMemory::Memzero(&ClonedQuantizedBuffer[StateIt], sizeof(ClonedQuantizedBuffer[StateIt]));
}
bHasClonedQuantizedState = false;
}
}
void FTestInstancedStructNetSerializerFixture::Dequantize()
{
UE_NET_ASSERT_TRUE(bHasQuantizedState);
FNetDequantizeArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Source = NetSerializerValuePointer(&QuantizedBuffer[0]);
Args.Target = bIsTestingArray ? NetSerializerValuePointer(&InstancedStructArray1) : NetSerializerValuePointer(&InstancedStruct1);
GetInstancedStructNetSerializer(bIsTestingArray)->Dequantize(NetSerializationContext, Args);
}
bool FTestInstancedStructNetSerializerFixture::IsEqual(bool bQuantized)
{
if (bQuantized)
{
UE_NET_EXPECT_TRUE(bHasQuantizedState);
if (!bHasQuantizedState)
{
return false;
}
UE_NET_EXPECT_TRUE(bHasClonedQuantizedState);
if (!bHasClonedQuantizedState)
{
return false;
}
}
FNetIsEqualArgs Args = {};
if (bQuantized)
{
Args.Source0 = NetSerializerValuePointer(&QuantizedBuffer[0]);
Args.Source1 = NetSerializerValuePointer(&ClonedQuantizedBuffer[0]);
}
else
{
Args.Source0 = bIsTestingArray ? NetSerializerValuePointer(&InstancedStructArray0) : NetSerializerValuePointer(&InstancedStruct0);
Args.Source1 = bIsTestingArray ? NetSerializerValuePointer(&InstancedStructArray1) : NetSerializerValuePointer(&InstancedStruct1);
}
Args.bStateIsQuantized = bQuantized;
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
return GetInstancedStructNetSerializer(bIsTestingArray)->IsEqual(NetSerializationContext, Args);
}
void FTestInstancedStructNetSerializerFixture::Validate()
{
FNetValidateArgs Args = {};
Args.NetSerializerConfig = NetSerializerConfigParam(GetInstancedStructNetSerializerConfig(bIsTestingArray));
Args.Source = bIsTestingArray ? NetSerializerValuePointer(&InstancedStructArray0) : NetSerializerValuePointer(&InstancedStruct0);
GetInstancedStructNetSerializer(bIsTestingArray)->Validate(NetSerializationContext, Args);
}
void FTestInstancedStructNetSerializerFixture::SetNonDefaultInstanceState()
{
InstancedStruct0.InitializeAs<FStructForInstancedStructTestA>();
InstancedStruct0.GetMutable<FStructForInstancedStructTestA>().SomeUint16 += 4711U;
}
void FTestInstancedStructNetSerializerFixture::SetNonDefaultArrayState()
{
InstancedStructArray0.Empty(7);
InstancedStructArray0.SetNum(7);
InstancedStructArray0[0].InitializeAs<FStructForInstancedStructTestA>();
InstancedStructArray0[1].InitializeAs<FStructForInstancedStructTestB>();
InstancedStructArray0[1].GetMutable<FStructForInstancedStructTestB>().SomeFloat = 1234.5f;
InstancedStructArray0[2].Reset();
InstancedStructArray0[3].InitializeAs<FStructForInstancedStructTestC>();
InstancedStructArray0[3].GetMutable<FStructForInstancedStructTestC>().SomeBool ^= true;
InstancedStructArray0[4].Reset();
InstancedStructArray0[5].InitializeAs<FStructForInstancedStructTestWithArray>();
InstancedStructArray0[6].InitializeAs<FStructForInstancedStructTestWithObjectReference>();
}
const FNetSerializer* FTestInstancedStructNetSerializerFixture::GetInstancedStructNetSerializer(bool bIsArray) const
{
if (bIsArray)
{
if (const FReplicationStateDescriptor* Desc = InstancedStructArrayNetSerializerConfig.StateDescriptor.GetReference())
{
return Desc->MemberSerializerDescriptors[0].Serializer;
}
}
else
{
if (const FReplicationStateDescriptor* Desc = InstancedStructNetSerializerConfig.StateDescriptor.GetReference())
{
return Desc->MemberSerializerDescriptors[0].Serializer;
}
}
return nullptr;
}
const FNetSerializerConfig* FTestInstancedStructNetSerializerFixture::GetInstancedStructNetSerializerConfig(bool bIsArray) const
{
if (bIsArray)
{
if (const FReplicationStateDescriptor* Desc = InstancedStructArrayNetSerializerConfig.StateDescriptor.GetReference())
{
return Desc->MemberSerializerDescriptors[0].SerializerConfig;
}
}
else
{
if (const FReplicationStateDescriptor* Desc = InstancedStructNetSerializerConfig.StateDescriptor.GetReference())
{
return Desc->MemberSerializerDescriptors[0].SerializerConfig;
}
}
return nullptr;
}
}
namespace UE::Net
{
void FStructForInstancedStructTestWithCustomApplyNetSerializer::Serialize(FNetSerializationContext& Context, const FNetSerializeArgs& Args)
{
const QuantizedType Value = *reinterpret_cast<const QuantizedType*>(Args.Source);
Context.GetBitStreamWriter()->WriteBits(Value, 32);
}
void FStructForInstancedStructTestWithCustomApplyNetSerializer::Deserialize(FNetSerializationContext& Context, const FNetDeserializeArgs& Args)
{
QuantizedType& Target = *reinterpret_cast<QuantizedType*>(Args.Target);
Target = Context.GetBitStreamReader()->ReadBits(32);
}
void FStructForInstancedStructTestWithCustomApplyNetSerializer::Quantize(FNetSerializationContext&, const FNetQuantizeArgs& Args)
{
const SourceType& Source = *reinterpret_cast<const SourceType*>(Args.Source);
QuantizedType& Target = *reinterpret_cast<QuantizedType*>(Args.Target);
Target = Source.Uint;
}
void FStructForInstancedStructTestWithCustomApplyNetSerializer::Dequantize(FNetSerializationContext&, const FNetDequantizeArgs& Args)
{
const QuantizedType& Source = *reinterpret_cast<const QuantizedType*>(Args.Source);
SourceType& Target = *reinterpret_cast<SourceType*>(Args.Target);
Target.Uint = Source;
}
bool FStructForInstancedStructTestWithCustomApplyNetSerializer::IsEqual(FNetSerializationContext&, const FNetIsEqualArgs& Args)
{
if (Args.bStateIsQuantized)
{
const QuantizedType& QuantizedValue0 = *reinterpret_cast<const QuantizedType*>(Args.Source0);
const QuantizedType& QuantizedValue1 = *reinterpret_cast<const QuantizedType*>(Args.Source1);
return QuantizedValue0 == QuantizedValue1;
}
else
{
const SourceType& SourceValue0 = *reinterpret_cast<const SourceType*>(Args.Source0);
const SourceType& SourceValue1 = *reinterpret_cast<const SourceType*>(Args.Source1);
return SourceValue0.Uint == SourceValue1.Uint;
}
}
void FStructForInstancedStructTestWithCustomApplyNetSerializer::Apply(FNetSerializationContext& Context, const FNetApplyArgs& Args)
{
const SourceType& Source = *reinterpret_cast<const SourceType*>(Args.Source);
SourceType& Target = *reinterpret_cast<SourceType*>(Args.Target);
Target.Uint = Source.Uint;
Target.ApplyCallCount++;
}
FStructForInstancedStructTestWithCustomApplyNetSerializer::FNetSerializerRegistryDelegates::~FNetSerializerRegistryDelegates()
{
UE_NET_UNREGISTER_NETSERIALIZER_INFO(StructForInstancedStructTestWithCustomApplyNetSerializer);
}
void FStructForInstancedStructTestWithCustomApplyNetSerializer::FNetSerializerRegistryDelegates::OnPreFreezeNetSerializerRegistry()
{
UE_NET_REGISTER_NETSERIALIZER_INFO(StructForInstancedStructTestWithCustomApplyNetSerializer);
}
void FStructForInstancedStructTestWithCustomSerializerNetSerializer::Serialize(FNetSerializationContext& Context, const FNetSerializeArgs& Args)
{
const QuantizedType Value = *reinterpret_cast<const QuantizedType*>(Args.Source);
Context.GetBitStreamWriter()->WriteBits(Value, 32);
}
void FStructForInstancedStructTestWithCustomSerializerNetSerializer::Deserialize(FNetSerializationContext& Context, const FNetDeserializeArgs& Args)
{
QuantizedType& Target = *reinterpret_cast<QuantizedType*>(Args.Target);
Target = Context.GetBitStreamReader()->ReadBits(32);
}
void FStructForInstancedStructTestWithCustomSerializerNetSerializer::Quantize(FNetSerializationContext&, const FNetQuantizeArgs& Args)
{
const SourceType& Source = *reinterpret_cast<const SourceType*>(Args.Source);
QuantizedType& Target = *reinterpret_cast<QuantizedType*>(Args.Target);
Target = Source.Uint;
}
void FStructForInstancedStructTestWithCustomSerializerNetSerializer::Dequantize(FNetSerializationContext&, const FNetDequantizeArgs& Args)
{
const QuantizedType& Source = *reinterpret_cast<const QuantizedType*>(Args.Source);
SourceType& Target = *reinterpret_cast<SourceType*>(Args.Target);
Target.Uint = Source;
}
bool FStructForInstancedStructTestWithCustomSerializerNetSerializer::IsEqual(FNetSerializationContext&, const FNetIsEqualArgs& Args)
{
if (Args.bStateIsQuantized)
{
const QuantizedType& QuantizedValue0 = *reinterpret_cast<const QuantizedType*>(Args.Source0);
const QuantizedType& QuantizedValue1 = *reinterpret_cast<const QuantizedType*>(Args.Source1);
return QuantizedValue0 == QuantizedValue1;
}
else
{
const SourceType& SourceValue0 = *reinterpret_cast<const SourceType*>(Args.Source0);
const SourceType& SourceValue1 = *reinterpret_cast<const SourceType*>(Args.Source1);
return SourceValue0.Uint == SourceValue1.Uint;
}
}
FStructForInstancedStructTestWithCustomSerializerNetSerializer::FNetSerializerRegistryDelegates::~FNetSerializerRegistryDelegates()
{
UE_NET_UNREGISTER_NETSERIALIZER_INFO(StructForInstancedStructTestWithCustomSerializerNetSerializer);
}
void FStructForInstancedStructTestWithCustomSerializerNetSerializer::FNetSerializerRegistryDelegates::OnPreFreezeNetSerializerRegistry()
{
UE_NET_REGISTER_NETSERIALIZER_INFO(StructForInstancedStructTestWithCustomSerializerNetSerializer);
}
}
//
void UInstancedStructNetSerializerTestObject::GetLifetimeReplicatedProps(TArray<class FLifetimeProperty>& OutLifetimeProps) const
{
FDoRepLifetimeParams Params;
Params.bIsPushBased = false;
DOREPLIFETIME_WITH_PARAMS_FAST(ThisClass, InstancedStruct, Params);
DOREPLIFETIME_WITH_PARAMS_FAST(ThisClass, InstancedStructArray, Params);
DOREPLIFETIME_WITH_PARAMS_FAST(ThisClass, StructWithInstancedStructArray, Params);
}
void UInstancedStructNetSerializerTestObject::RegisterReplicationFragments(UE::Net::FFragmentRegistrationContext& Context, UE::Net::EFragmentRegistrationFlags RegistrationFlags)
{
UE::Net::FReplicationFragmentUtil::CreateAndRegisterFragmentsForObject(this, Context, RegistrationFlags);
}