TMap replication still not supported?

TMap replication still seems unsupported, or am I doing something wrong?

A mention of this is here already: TMap<> Replication - exposing to Unreal reflection. - Feedback for Unreal Engine team - Unreal Engine Forums

Trying to get it to replicate seems to always lead to “Deprecated Code Path” in PropertyMap.cpp

bool UMapProperty::NetSerializeItem( FArchive& Ar, UPackageMap* Map, void* Data, TArray<uint8> * MetaData ) const
{
	UE_LOG( LogProperty, Fatal, TEXT( "Deprecated code path" ) );
	return 1;
}
1 Like

To add a little more info, the relevant part of the call stack: UE4Editor-CoreUObject.dll!UMapProperty::NetSerializeItem(FArchive & Ar, UPacka - Pastebin.com

I’m getting the same issue/crash with a blueprint struct containing a tmap from GUID → Blueprint struct.

Getting the same results in 4.17 :[

…and 4.18

Has anyone tried in 4.19? Right now still using UStructs in many places where TMap would just fit a lot nicer if properly supported with replication. As useful and amazing as structs can be in few places TMap would just be so much cleaner to use in my project.

I am posting this in case it might be useful as a simple starting place for someone. Tested in 4.19 only, and only for simple types (ie. FString). The TMAP is placed inside of a USTRUCT where NetSerialize moves key/values between TMAP and TARRAY’s before/after network transport.

USTRUCT(BlueprintType)
struct FStructWithMap
{
	GENERATED_BODY()
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
    TMap<FString, FString> StringMap;
 
    TArray<FString> StringKeys;
    TArray<FString> StringValues;


	bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)
	{
		if (Ar.IsLoading())
		{
			// Move data to Map
			Ar << StringKeys;
			Ar << StringValues;
			for (auto It = StringKeys.CreateConstIterator(); It; ++It)
			{
				StringMap.Add(StringKeys[It.GetIndex()], StringValues[It.GetIndex()]);
			}
		} else {
			// Move data to Arrays
			StringMap.GenerateKeyArray(StringKeys);
			StringMap.GenerateValueArray(StringValues);
			Ar << StringKeys;
			Ar << StringValues;
		}
		StringKeys.Empty();
		StringValues.Empty();

		bOutSuccess = true;
		return true;
	}
};
 
template<>
struct TStructOpsTypeTraits<FStructWithMap> : public TStructOpsTypeTraitsBase2<FStructWithMap>
{
	enum
	{
		WithNetSerializer = true
	};
};
4 Likes

Same for 4.19.
Are TMap going to be replicated any time soon ?
I mean, it seems like something pretty much essential.

Well it’s not good. Work around is just mess

this is the cleanest implementation of tmap replication workaround i have seen so far.

StringKeys and StringValues should probably be local variables in NetSerialize() – they don’t need to be member variables for this.

How would you get this to work with a TMap with a struct for the values? It doesn’t seem to like using AR << on the struct values.