I am attempting to create a 3dArray struct with a custom NetSerializer that compresses the array first, send the compressed data, then decompressed at the destination. This is what I have so far.
USTRUCT()
struct F3DArray
{
GENERATED_USTRUCT_BODY()
F3DArray()
{
Data.Init(false, FMath::Pow(32, 3));
}
bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
{
UE_LOG(LogTemp, Warning, TEXT("Replicate"));
bOutSuccess = true;
if (Ar.IsSaving())
{
TArray<uint8> Compressed;
TArray<uint8> UncompressedBuffer;
FMemoryWriter ArWriter(UncompressedBuffer);
ArWriter << Blocks;
const int32 UncompressedSize = UncompressedBuffer.Num();
const int32 HeaderSize = sizeof(int32);
Compressed.Init(0, HeaderSize + FMath::TruncToInt(1.1f * UncompressedSize));
int32 CompressedSize = Compressed.Num() - HeaderSize;
uint8* DestBuffer = Compressed.GetData();
FMemory::Memcpy(DestBuffer, &UncompressedSize, HeaderSize);
DestBuffer += HeaderSize;
FCompression::CompressMemory(ECompressionFlags::COMPRESS_ZLIB, DestBuffer, CompressedSize, UncompressedBuffer.GetData(), UncompressedSize);
Compressed.SetNum(CompressedSize + HeaderSize, false);
Ar << Compressed;
return true;
}
else if (Ar.IsLoading())
{
TArray<uint8> Compressed;
Ar << Compressed;
TArray<uint8> UncompressedBuffer;
int32 UncompressedSize = 0;
const int32 HeaderSize = sizeof(int32);
uint8* SrcBuffer = Compressed.GetData();
FMemory::Memcpy(&UncompressedSize, SrcBuffer, HeaderSize);
SrcBuffer += HeaderSize;
const int32 CompressedSize = Compressed.Num() - HeaderSize;
UncompressedBuffer.AddZeroed(UncompressedSize);
FCompression::UncompressMemory(ECompressionFlags::COMPRESS_ZLIB, UncompressedBuffer.GetData(), UncompressedSize, SrcBuffer, CompressedSize);
FMemoryReader ArReader(UncompressedBuffer);
ArReader << Data;
return true;
}
return false;
}
private:
TArray<bool> Data;
};
template<>
struct TStructOpsTypeTraits<F3DArray> : public TStructOpsTypeTraitsBase
{
enum
{
WithNetSerializer = true,
};
};
So, what happens is this - I have some generic Actor in my scene that has this struct as a member variable. I have set it to ReplicateUsing a function. This function IS being called as I have it printing a log statement to the console. The “Data” array is not being replicated though.
Here are some code snippets to show the implementation of a some of the things just mentioned:
// These are in the actors class
UPROPERTY(ReplicatedUsing = OnRep_MarkUpdate)
F3DArray Data;
UFUNCTION()
void OnRep_MarkUpdate();
// This is in the actor cpp
void AReplicateTest::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
DOREPLIFETIME(AReplicateTest, Data);
}
void AReplicateTest::OnRep_MarkUpdate()
{
UE_LOG(LogTemp, Warning, TEXT("Replicated"));
}
And OnRep_MarkUpdate() is being called as I do see the log print out from that - I do NOT however see any logging from the NetSerialize() function included in the USTRUCT. I have also test the compression on it’s own else where, it works fine. I may be incorrectly using the FArchive in NetSerialize() though…
Also, if i place a break point in the OnRep_MarkUpdate() function it does break there, but if I put a break point in the NetSerlialize() function it is NOT hit.