Download

Custom NetSerialize on USTRUCT

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.