684 lines
21 KiB
C
684 lines
21 KiB
C
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||
|
|
|
||
|
|
#pragma once
|
||
|
|
|
||
|
|
#include "CoreMinimal.h"
|
||
|
|
#include "UObject/ObjectMacros.h"
|
||
|
|
#include "UObject/Object.h"
|
||
|
|
#include "UObject/Class.h"
|
||
|
|
#include "UObject/WeakObjectPtr.h"
|
||
|
|
#include "Serialization/BitReader.h"
|
||
|
|
#include "Serialization/BitWriter.h"
|
||
|
|
#include "Misc/NetworkGuid.h"
|
||
|
|
#include "UObject/CoreNetTypes.h"
|
||
|
|
#include "UObject/SoftObjectPath.h"
|
||
|
|
#include "UObject/Field.h"
|
||
|
|
#include "Trace/Config.h"
|
||
|
|
|
||
|
|
class FOutBunch;
|
||
|
|
class INetDeltaBaseState;
|
||
|
|
class FNetTraceCollector;
|
||
|
|
|
||
|
|
DECLARE_DELEGATE_RetVal_OneParam(bool, FNetObjectIsDynamic, const UObject*);
|
||
|
|
|
||
|
|
//
|
||
|
|
// Information about a field.
|
||
|
|
//
|
||
|
|
class COREUOBJECT_API FFieldNetCache
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
FFieldVariant Field;
|
||
|
|
int32 FieldNetIndex;
|
||
|
|
uint32 FieldChecksum;
|
||
|
|
mutable bool bIncompatible;
|
||
|
|
|
||
|
|
FFieldNetCache()
|
||
|
|
{}
|
||
|
|
FFieldNetCache(FFieldVariant InField, int32 InFieldNetIndex, uint32 InFieldChecksum)
|
||
|
|
: Field(InField), FieldNetIndex(InFieldNetIndex), FieldChecksum(InFieldChecksum), bIncompatible(false)
|
||
|
|
{}
|
||
|
|
};
|
||
|
|
|
||
|
|
//
|
||
|
|
// Information about a class, cached for network coordination.
|
||
|
|
//
|
||
|
|
class COREUOBJECT_API FClassNetCache
|
||
|
|
{
|
||
|
|
friend class FClassNetCacheMgr;
|
||
|
|
|
||
|
|
public:
|
||
|
|
FClassNetCache();
|
||
|
|
FClassNetCache(const UClass* Class);
|
||
|
|
|
||
|
|
int32 GetMaxIndex() const
|
||
|
|
{
|
||
|
|
return FieldsBase + Fields.Num();
|
||
|
|
}
|
||
|
|
|
||
|
|
const FFieldNetCache* GetFromField(FFieldVariant Field) const
|
||
|
|
{
|
||
|
|
FFieldNetCache* Result = NULL;
|
||
|
|
|
||
|
|
for (const FClassNetCache* C = this; C; C = C->Super)
|
||
|
|
{
|
||
|
|
if ((Result = C->FieldMap.FindRef(Field.GetRawPointer())) != NULL)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return Result;
|
||
|
|
}
|
||
|
|
|
||
|
|
const FFieldNetCache* GetFromChecksum(const uint32 Checksum) const
|
||
|
|
{
|
||
|
|
FFieldNetCache* Result = NULL;
|
||
|
|
|
||
|
|
for (const FClassNetCache* C = this; C; C = C->Super)
|
||
|
|
{
|
||
|
|
if ((Result = C->FieldChecksumMap.FindRef(Checksum)) != NULL)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return Result;
|
||
|
|
}
|
||
|
|
|
||
|
|
const FFieldNetCache* GetFromIndex(const int32 Index) const
|
||
|
|
{
|
||
|
|
for (const FClassNetCache* C = this; C; C = C->Super)
|
||
|
|
{
|
||
|
|
if (Index >= C->FieldsBase && Index < C->FieldsBase + C->Fields.Num())
|
||
|
|
{
|
||
|
|
return &C->Fields[Index - C->FieldsBase];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint32 GetClassChecksum() const { return ClassChecksum; }
|
||
|
|
|
||
|
|
const FClassNetCache* GetSuper() const { return Super; }
|
||
|
|
const TArray<FFieldNetCache>& GetFields() const { return Fields; }
|
||
|
|
|
||
|
|
void CountBytes(FArchive& Ar) const;
|
||
|
|
|
||
|
|
private:
|
||
|
|
int32 FieldsBase;
|
||
|
|
const FClassNetCache* Super;
|
||
|
|
TWeakObjectPtr<const UClass> Class;
|
||
|
|
uint32 ClassChecksum;
|
||
|
|
TArray<FFieldNetCache> Fields;
|
||
|
|
TMap<void*, FFieldNetCache*> FieldMap;
|
||
|
|
TMap<uint32, FFieldNetCache*> FieldChecksumMap;
|
||
|
|
};
|
||
|
|
|
||
|
|
class COREUOBJECT_API FClassNetCacheMgr
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
FClassNetCacheMgr(): bDebugChecksum(false), DebugChecksumIndent(0) {}
|
||
|
|
~FClassNetCacheMgr() { ClearClassNetCache(); }
|
||
|
|
|
||
|
|
/** get the cached field to index mappings for the given class */
|
||
|
|
const FClassNetCache* GetClassNetCache(UClass* Class);
|
||
|
|
void ClearClassNetCache();
|
||
|
|
|
||
|
|
void SortProperties(TArray<FProperty*>& Properties) const;
|
||
|
|
uint32 SortedStructFieldsChecksum(const UStruct* Struct, uint32 Checksum) const;
|
||
|
|
uint32 GetPropertyChecksum(const FProperty* Property, uint32 Checksum, const bool bIncludeChildren) const;
|
||
|
|
uint32 GetFunctionChecksum(const UFunction* Function, uint32 Checksum) const;
|
||
|
|
uint32 GetFieldChecksum(const UField* Field, uint32 Checksum) const;
|
||
|
|
|
||
|
|
bool bDebugChecksum;
|
||
|
|
int DebugChecksumIndent;
|
||
|
|
|
||
|
|
void CountBytes(FArchive& Ar) const;
|
||
|
|
|
||
|
|
private:
|
||
|
|
TMap<TWeakObjectPtr<const UClass>, FClassNetCache*> ClassFieldIndices;
|
||
|
|
};
|
||
|
|
|
||
|
|
//
|
||
|
|
// Maps objects and names to and from indices for network communication.
|
||
|
|
//
|
||
|
|
class COREUOBJECT_API UPackageMap: public UObject
|
||
|
|
{
|
||
|
|
DECLARE_CLASS_INTRINSIC(UPackageMap, UObject, CLASS_Transient | CLASS_Abstract | 0, TEXT("/Script/CoreUObject"));
|
||
|
|
|
||
|
|
virtual bool WriteObject(FArchive& Ar, UObject* InOuter, FNetworkGUID NetGUID, FString ObjName) { return false; }
|
||
|
|
|
||
|
|
// @todo document
|
||
|
|
virtual bool SerializeObject(FArchive& Ar, UClass* InClass, UObject*& Obj, FNetworkGUID* OutNetGUID = NULL) { return false; }
|
||
|
|
|
||
|
|
// @todo document
|
||
|
|
virtual bool SerializeName(FArchive& Ar, FName& InName);
|
||
|
|
|
||
|
|
static bool StaticSerializeName(FArchive& Ar, FName& InName);
|
||
|
|
|
||
|
|
virtual UObject* ResolvePathAndAssignNetGUID(const FNetworkGUID& NetGUID, const FString& PathName) { return NULL; }
|
||
|
|
|
||
|
|
virtual bool SerializeNewActor(FArchive& Ar, class UActorChannel* Channel, class AActor*& Actor) { return false; }
|
||
|
|
|
||
|
|
virtual void ReceivedNak(const int32 NakPacketId) {}
|
||
|
|
virtual void ReceivedAck(const int32 AckPacketId) {}
|
||
|
|
virtual void NotifyBunchCommit(const int32 OutPacketId, const FOutBunch* OutBunch) {}
|
||
|
|
|
||
|
|
virtual void GetNetGUIDStats(int32& AckCount, int32& UnAckCount, int32& PendingCount) {}
|
||
|
|
|
||
|
|
virtual void NotifyStreamingLevelUnload(UObject* UnloadedLevel) {}
|
||
|
|
|
||
|
|
virtual bool PrintExportBatch() { return false; }
|
||
|
|
|
||
|
|
void SetDebugContextString(const FString& Str) { DebugContextString = Str; }
|
||
|
|
void ClearDebugContextString() { DebugContextString.Empty(); }
|
||
|
|
|
||
|
|
void ResetTrackedGuids(bool bShouldTrack)
|
||
|
|
{
|
||
|
|
TrackedUnmappedNetGuids.Empty();
|
||
|
|
TrackedMappedDynamicNetGuids.Empty();
|
||
|
|
bShouldTrackUnmappedGuids = bShouldTrack;
|
||
|
|
}
|
||
|
|
const TSet<FNetworkGUID>& GetTrackedUnmappedGuids() const { return TrackedUnmappedNetGuids; }
|
||
|
|
const TSet<FNetworkGUID>& GetTrackedDynamicMappedGuids() const { return TrackedMappedDynamicNetGuids; }
|
||
|
|
|
||
|
|
// For sync load debugging with LogNetSyncLoads
|
||
|
|
virtual void ResetTrackedSyncLoadedGuids() {}
|
||
|
|
virtual void ReportSyncLoadsForProperty(const FProperty* Property, const UObject* Object) {}
|
||
|
|
|
||
|
|
virtual void LogDebugInfo(FOutputDevice& Ar) {}
|
||
|
|
virtual UObject* GetObjectFromNetGUID(const FNetworkGUID& NetGUID, const bool bIgnoreMustBeMapped) { return NULL; }
|
||
|
|
virtual FNetworkGUID GetNetGUIDFromObject(const UObject* InObject) const { return FNetworkGUID(); }
|
||
|
|
virtual bool IsGUIDBroken(const FNetworkGUID& NetGUID, const bool bMustBeRegistered) const { return false; }
|
||
|
|
|
||
|
|
virtual void Serialize(FArchive& Ar) override;
|
||
|
|
|
||
|
|
protected:
|
||
|
|
UE_DEPRECATED(4.25, "bSuppressLogs will be removed in a future release.")
|
||
|
|
bool bSuppressLogs;
|
||
|
|
|
||
|
|
bool bShouldTrackUnmappedGuids;
|
||
|
|
TSet<FNetworkGUID> TrackedUnmappedNetGuids;
|
||
|
|
TSet<FNetworkGUID> TrackedMappedDynamicNetGuids;
|
||
|
|
|
||
|
|
FString DebugContextString;
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Represents a range of PacketIDs, inclusive */
|
||
|
|
struct FPacketIdRange
|
||
|
|
{
|
||
|
|
FPacketIdRange(int32 _First, int32 _Last): First(_First), Last(_Last) {}
|
||
|
|
FPacketIdRange(int32 PacketId): First(PacketId), Last(PacketId) {}
|
||
|
|
FPacketIdRange(): First(INDEX_NONE), Last(INDEX_NONE) {}
|
||
|
|
int32 First;
|
||
|
|
int32 Last;
|
||
|
|
|
||
|
|
bool InRange(int32 PacketId) const
|
||
|
|
{
|
||
|
|
return (First <= PacketId && PacketId <= Last);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Information for tracking retirement and retransmission of a property. */
|
||
|
|
struct FPropertyRetirement
|
||
|
|
{
|
||
|
|
#if !UE_BUILD_SHIPPING
|
||
|
|
static const uint32 ExpectedSanityTag = 0xDF41C9A3;
|
||
|
|
|
||
|
|
uint32 SanityTag;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
FPropertyRetirement* Next;
|
||
|
|
|
||
|
|
TSharedPtr<class INetDeltaBaseState> DynamicState;
|
||
|
|
|
||
|
|
FPacketIdRange OutPacketIdRange;
|
||
|
|
uint32 FastArrayChangelistHistory;
|
||
|
|
|
||
|
|
FPropertyRetirement():
|
||
|
|
#if !UE_BUILD_SHIPPING
|
||
|
|
SanityTag(ExpectedSanityTag),
|
||
|
|
#endif
|
||
|
|
Next(nullptr),
|
||
|
|
DynamicState(nullptr),
|
||
|
|
FastArrayChangelistHistory(0)
|
||
|
|
{}
|
||
|
|
|
||
|
|
void CountBytes(FArchive& Ar) const;
|
||
|
|
};
|
||
|
|
|
||
|
|
/** FLifetimeProperty
|
||
|
|
* This class is used to track a property that is marked to be replicated for the lifetime of the actor channel.
|
||
|
|
* This doesn't mean the property will necessarily always be replicated, it just means:
|
||
|
|
* "check this property for replication for the life of the actor, and I don't want to think about it anymore"
|
||
|
|
* A secondary condition can also be used to skip replication based on the condition results
|
||
|
|
*/
|
||
|
|
class FLifetimeProperty
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
uint16 RepIndex;
|
||
|
|
ELifetimeCondition Condition;
|
||
|
|
ELifetimeRepNotifyCondition RepNotifyCondition;
|
||
|
|
bool bIsPushBased;
|
||
|
|
|
||
|
|
FLifetimeProperty()
|
||
|
|
: RepIndex(0), Condition(COND_None), RepNotifyCondition(REPNOTIFY_OnChanged), bIsPushBased(false)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
FLifetimeProperty(int32 InRepIndex)
|
||
|
|
: RepIndex(InRepIndex), Condition(COND_None), RepNotifyCondition(REPNOTIFY_OnChanged), bIsPushBased(false)
|
||
|
|
{
|
||
|
|
check(InRepIndex <= 65535);
|
||
|
|
}
|
||
|
|
|
||
|
|
FLifetimeProperty(int32 InRepIndex, ELifetimeCondition InCondition, ELifetimeRepNotifyCondition InRepNotifyCondition = REPNOTIFY_OnChanged, bool bInIsPushBased = false)
|
||
|
|
: RepIndex(InRepIndex), Condition(InCondition), RepNotifyCondition(InRepNotifyCondition), bIsPushBased(bInIsPushBased)
|
||
|
|
{
|
||
|
|
check(InRepIndex <= 65535);
|
||
|
|
}
|
||
|
|
|
||
|
|
inline bool operator==(const FLifetimeProperty& Other) const
|
||
|
|
{
|
||
|
|
if (RepIndex == Other.RepIndex)
|
||
|
|
{
|
||
|
|
// Can't have different conditions if the RepIndex matches, doesn't make sense
|
||
|
|
check(Condition == Other.Condition);
|
||
|
|
check(RepNotifyCondition == Other.RepNotifyCondition);
|
||
|
|
check(bIsPushBased == Other.bIsPushBased);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
template <>
|
||
|
|
struct TIsZeroConstructType<FLifetimeProperty>
|
||
|
|
{
|
||
|
|
enum
|
||
|
|
{
|
||
|
|
Value = true
|
||
|
|
};
|
||
|
|
};
|
||
|
|
|
||
|
|
GENERATE_MEMBER_FUNCTION_CHECK(GetLifetimeReplicatedProps, void, const, TArray<FLifetimeProperty>&)
|
||
|
|
|
||
|
|
// Consider adding UE_NET_TRACE_ENABLE to build config, for now we use the UE_TRACE_ENABLED as NetTrace is not support unless tracing is enabled
|
||
|
|
#if UE_TRACE_ENABLED
|
||
|
|
/**
|
||
|
|
* We pass a NetTraceCollector along with the NetBitWriter in order avoid modifying all API`s where we want to be able to collect Network stats
|
||
|
|
* Since the pointer to the collector is temporary we need to avoid copying it around by accident
|
||
|
|
*/
|
||
|
|
class FNetTraceCollectorDoNotCopyWrapper
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
FNetTraceCollectorDoNotCopyWrapper(): Collector(nullptr) {}
|
||
|
|
FNetTraceCollectorDoNotCopyWrapper(const FNetTraceCollectorDoNotCopyWrapper&): Collector(nullptr) {}
|
||
|
|
FNetTraceCollectorDoNotCopyWrapper(FNetTraceCollectorDoNotCopyWrapper&&) { Collector = nullptr; }
|
||
|
|
FNetTraceCollectorDoNotCopyWrapper& operator=(const FNetTraceCollectorDoNotCopyWrapper& Other)
|
||
|
|
{
|
||
|
|
Collector = nullptr;
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
FNetTraceCollectorDoNotCopyWrapper& operator=(FNetTraceCollectorDoNotCopyWrapper&&)
|
||
|
|
{
|
||
|
|
Collector = nullptr;
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Set(FNetTraceCollector* InCollector) { Collector = InCollector; }
|
||
|
|
FNetTraceCollector* Get() const { return Collector; }
|
||
|
|
|
||
|
|
private:
|
||
|
|
FNetTraceCollector* Collector;
|
||
|
|
};
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/**
|
||
|
|
* FNetBitWriter
|
||
|
|
* A bit writer that serializes FNames and UObject* through
|
||
|
|
* a network packagemap.
|
||
|
|
*/
|
||
|
|
class COREUOBJECT_API FNetBitWriter: public FBitWriter
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
FNetBitWriter(UPackageMap* InPackageMap, int64 InMaxBits);
|
||
|
|
FNetBitWriter(int64 InMaxBits);
|
||
|
|
FNetBitWriter();
|
||
|
|
|
||
|
|
class UPackageMap* PackageMap;
|
||
|
|
|
||
|
|
#if UE_TRACE_ENABLED
|
||
|
|
FNetTraceCollectorDoNotCopyWrapper TraceCollector;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
virtual FArchive& operator<<(FName& Name) override;
|
||
|
|
virtual FArchive& operator<<(UObject*& Object) override;
|
||
|
|
virtual FArchive& operator<<(FSoftObjectPath& Value) override;
|
||
|
|
virtual FArchive& operator<<(FSoftObjectPtr& Value) override;
|
||
|
|
virtual FArchive& operator<<(struct FWeakObjectPtr& Value) override;
|
||
|
|
|
||
|
|
virtual void CountMemory(FArchive& Ar) const override;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* FNetBitReader
|
||
|
|
* A bit reader that serializes FNames and UObject* through
|
||
|
|
* a network packagemap.
|
||
|
|
*/
|
||
|
|
class COREUOBJECT_API FNetBitReader: public FBitReader
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
FNetBitReader(UPackageMap* InPackageMap = NULL, uint8* Src = NULL, int64 CountBits = 0);
|
||
|
|
|
||
|
|
class UPackageMap* PackageMap;
|
||
|
|
|
||
|
|
virtual FArchive& operator<<(FName& Name) override;
|
||
|
|
virtual FArchive& operator<<(UObject*& Object) override;
|
||
|
|
virtual FArchive& operator<<(FSoftObjectPath& Value) override;
|
||
|
|
virtual FArchive& operator<<(FSoftObjectPtr& Value) override;
|
||
|
|
virtual FArchive& operator<<(struct FWeakObjectPtr& Value) override;
|
||
|
|
|
||
|
|
virtual void CountMemory(FArchive& Ar) const override;
|
||
|
|
};
|
||
|
|
|
||
|
|
bool FORCEINLINE NetworkGuidSetsAreSame(const TSet<FNetworkGUID>& A, const TSet<FNetworkGUID>& B)
|
||
|
|
{
|
||
|
|
if (A.Num() != B.Num())
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (const FNetworkGUID& CompareGuid: A)
|
||
|
|
{
|
||
|
|
if (!B.Contains(CompareGuid))
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* INetDeltaBaseState
|
||
|
|
* An abstract interface for the base state used in net delta serialization. See notes in NetSerialization.h
|
||
|
|
*/
|
||
|
|
class INetDeltaBaseState: public TSharedFromThis<INetDeltaBaseState>
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
INetDeltaBaseState()
|
||
|
|
: LastAckedHistory(0), ChangelistHistory(0)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
virtual ~INetDeltaBaseState() {}
|
||
|
|
|
||
|
|
virtual bool IsStateEqual(INetDeltaBaseState* Otherstate) = 0;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Used when tracking memory to gather the total size of a given instance.
|
||
|
|
* This should include the dynamically allocated data, as well as the classes size.
|
||
|
|
*/
|
||
|
|
virtual void CountBytes(FArchive& Ar) const {}
|
||
|
|
|
||
|
|
uint32 GetLastAckedHistory() const { return LastAckedHistory; }
|
||
|
|
void SetLastAckedHistory(uint32 InAckedHistory) { LastAckedHistory = InAckedHistory; }
|
||
|
|
|
||
|
|
uint32 GetChangelistHistory() const { return ChangelistHistory; }
|
||
|
|
void SetChangelistHistory(uint32 InChangelistHistory) { ChangelistHistory = InChangelistHistory; }
|
||
|
|
|
||
|
|
private:
|
||
|
|
uint32 LastAckedHistory;
|
||
|
|
uint32 ChangelistHistory;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct FNetDeltaSerializeInfo;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* An interface for handling serialization of Structs for networking.
|
||
|
|
*
|
||
|
|
* See notes in NetSerialization.h
|
||
|
|
*/
|
||
|
|
class COREUOBJECT_API INetSerializeCB
|
||
|
|
{
|
||
|
|
protected:
|
||
|
|
using FGuidReferencesMap = TMap<int32, class FGuidReferences>;
|
||
|
|
|
||
|
|
public:
|
||
|
|
INetSerializeCB() {}
|
||
|
|
|
||
|
|
virtual ~INetSerializeCB() {}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Serializes an entire struct to / from the given archive.
|
||
|
|
* It is up to callers to manage Guid References created during reads.
|
||
|
|
*
|
||
|
|
* @param Params NetDeltaSerialization Params to use.
|
||
|
|
* Object must be valid.
|
||
|
|
* Data must be valid.
|
||
|
|
* Connection must be valid.
|
||
|
|
* Map must be valid.
|
||
|
|
* Struct must point to the UScriptStruct of Data.
|
||
|
|
* Either Reader or Writer (but not both) must be valid.
|
||
|
|
* bOutHasMoreUnmapped will be used to return whether or not we have we have unmapped guids.
|
||
|
|
* Only used when reading.
|
||
|
|
*/
|
||
|
|
virtual void NetSerializeStruct(FNetDeltaSerializeInfo& Params) = 0;
|
||
|
|
|
||
|
|
UE_DEPRECATED(4.23, "Please use the version of NetSerializeStruct that accepts an FNetDeltaSerializeInfo reference")
|
||
|
|
virtual void NetSerializeStruct(
|
||
|
|
class UScriptStruct* Struct,
|
||
|
|
class FBitArchive& Ar,
|
||
|
|
class UPackageMap* Map,
|
||
|
|
void* Data,
|
||
|
|
bool& bHasUnmapped);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Gathers any guid references for a FastArraySerializer.
|
||
|
|
* @see GuidReferences.h for more info.
|
||
|
|
*/
|
||
|
|
virtual void GatherGuidReferencesForFastArray(struct FFastArrayDeltaSerializeParams& Params) = 0;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Moves a previously mapped guid to an unmapped state for a FastArraySerializer.
|
||
|
|
* @see GuidReferences.h for more info.
|
||
|
|
*
|
||
|
|
* @return True if the guid was found and unmapped.
|
||
|
|
*/
|
||
|
|
virtual bool MoveGuidToUnmappedForFastArray(struct FFastArrayDeltaSerializeParams& Params) = 0;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Updates any unmapped guid references for a FastArraySerializer.
|
||
|
|
* @see GuidReferences.h for more info.
|
||
|
|
*/
|
||
|
|
virtual void UpdateUnmappedGuidsForFastArray(struct FFastArrayDeltaSerializeParams& Params) = 0;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Similar to NetSerializeStruct, except serializes an entire FastArraySerializer at once
|
||
|
|
* instead of element by element.
|
||
|
|
*/
|
||
|
|
virtual bool NetDeltaSerializeForFastArray(struct FFastArrayDeltaSerializeParams& Params) = 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
class IRepChangedPropertyTracker
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
IRepChangedPropertyTracker() {}
|
||
|
|
virtual ~IRepChangedPropertyTracker() {}
|
||
|
|
|
||
|
|
virtual void SetCustomIsActiveOverride(
|
||
|
|
UObject* OwningObject,
|
||
|
|
const uint16 RepIndex,
|
||
|
|
const bool bIsActive) = 0;
|
||
|
|
|
||
|
|
virtual void SetExternalData(const uint8* Src, const int32 NumBits) = 0;
|
||
|
|
|
||
|
|
UE_DEPRECATED(4.26, "Will be removed in a future release.")
|
||
|
|
virtual bool IsReplay() const = 0;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Used when tracking memory to gather the total size of a given instance.
|
||
|
|
* This should include the dynamically allocated data, as well as the classes size.
|
||
|
|
*/
|
||
|
|
virtual void CountBytes(FArchive& Ar) const {};
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* FNetDeltaSerializeInfo
|
||
|
|
* This is the parameter structure for delta serialization. It is kind of a dumping ground for anything custom implementations may need.
|
||
|
|
*/
|
||
|
|
struct FNetDeltaSerializeInfo
|
||
|
|
{
|
||
|
|
/** Used when writing */
|
||
|
|
FBitWriter* Writer = nullptr;
|
||
|
|
|
||
|
|
/** Used when reading */
|
||
|
|
FBitReader* Reader = nullptr;
|
||
|
|
|
||
|
|
/** SharedPtr to new base state created by NetDeltaSerialize. Used when writing.*/
|
||
|
|
TSharedPtr<INetDeltaBaseState>* NewState = nullptr;
|
||
|
|
|
||
|
|
/** Pointer to the previous base state. Used when writing. */
|
||
|
|
INetDeltaBaseState* OldState = nullptr;
|
||
|
|
|
||
|
|
/** PackageMap that can be used to serialize objects and track Guid References. Used primarily when reading. */
|
||
|
|
class UPackageMap* Map = nullptr;
|
||
|
|
|
||
|
|
/** Connection that we're currently serializing data for. */
|
||
|
|
class UNetConnection* Connection = nullptr;
|
||
|
|
|
||
|
|
/** Pointer to the struct that we're serializing.*/
|
||
|
|
void* Data = nullptr;
|
||
|
|
|
||
|
|
/** Type of struct that we're serializing. */
|
||
|
|
class UStruct* Struct = nullptr;
|
||
|
|
|
||
|
|
/** Pointer to a NetSerializeCB implementation that can be used when serializing. */
|
||
|
|
INetSerializeCB* NetSerializeCB = nullptr;
|
||
|
|
|
||
|
|
/** If true, we are updating unmapped objects */
|
||
|
|
bool bUpdateUnmappedObjects = false;
|
||
|
|
|
||
|
|
/** If true, then we successfully mapped some unmapped objects. */
|
||
|
|
bool bOutSomeObjectsWereMapped = false;
|
||
|
|
|
||
|
|
/** Whether or not PreNetReceive has been called on the owning object. */
|
||
|
|
bool bCalledPreNetReceive = false;
|
||
|
|
|
||
|
|
/** Whether or not there are still some outstanding unmapped objects referenced by the struct. */
|
||
|
|
bool bOutHasMoreUnmapped = false;
|
||
|
|
|
||
|
|
/** Whether or not we changed Guid / Object references. Used when reading. */
|
||
|
|
bool bGuidListsChanged = false;
|
||
|
|
|
||
|
|
/** Whether or not we're sending / writing data from the client. */
|
||
|
|
bool bIsWritingOnClient = false;
|
||
|
|
|
||
|
|
//~ TODO: This feels hacky, and a better alternative might be something like connection specific
|
||
|
|
//~ capabilities.
|
||
|
|
|
||
|
|
/** Whether or not we support FFastArraySerializer::FastArrayDeltaSerialize_DeltaSerializeStructs */
|
||
|
|
bool bSupportsFastArrayDeltaStructSerialization = false;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Whether or the connection is completely reliable.
|
||
|
|
* We cache this off separate from UNetConnection so we can limit usage.
|
||
|
|
*/
|
||
|
|
bool bInternalAck = false;
|
||
|
|
|
||
|
|
/** The object that owns the struct we're serializing. */
|
||
|
|
UObject* Object = nullptr;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* When non-null, this indicates that we're gathering Guid References.
|
||
|
|
* Any Guids the struct is referencing should be added.
|
||
|
|
* This may contain gathered Guids from other structs, so do not clear this set.
|
||
|
|
*/
|
||
|
|
TSet<FNetworkGUID>* GatherGuidReferences = nullptr;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* When we're gathering guid references, ny memory used to track Guids can be added to this.
|
||
|
|
* This may be tracking Guid memory from other structs, so do not reset this.
|
||
|
|
* Note, this is not guaranteed to be valid when GatherGuidReferences is.
|
||
|
|
*/
|
||
|
|
int32* TrackedGuidMemoryBytes = nullptr;
|
||
|
|
|
||
|
|
/** When non-null, this indicates the given Guid has become unmapped and any references to it should be updated. */
|
||
|
|
const FNetworkGUID* MoveGuidToUnmapped = nullptr;
|
||
|
|
|
||
|
|
uint16 CustomDeltaIndex = INDEX_NONE;
|
||
|
|
|
||
|
|
// Debugging variables
|
||
|
|
FString DebugName;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct FEncryptionData
|
||
|
|
{
|
||
|
|
/** Encryption key */
|
||
|
|
TArray<uint8> Key;
|
||
|
|
/** Encryption fingerprint */
|
||
|
|
TArray<uint8> Fingerprint;
|
||
|
|
/** Encryption identifier */
|
||
|
|
FString Identifier;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Checksum macros for verifying archives stay in sync
|
||
|
|
*/
|
||
|
|
COREUOBJECT_API void SerializeChecksum(FArchive& Ar, uint32 x, bool ErrorOK);
|
||
|
|
|
||
|
|
#define NET_ENABLE_CHECKSUMS 0
|
||
|
|
|
||
|
|
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && NET_ENABLE_CHECKSUMS
|
||
|
|
|
||
|
|
#define NET_CHECKSUM_OR_END(Ser) \
|
||
|
|
{ \
|
||
|
|
SerializeChecksum(Ser,0xE282FA84, true); \
|
||
|
|
}
|
||
|
|
|
||
|
|
#define NET_CHECKSUM(Ser) \
|
||
|
|
{ \
|
||
|
|
SerializeChecksum(Ser,0xE282FA84, false); \
|
||
|
|
}
|
||
|
|
|
||
|
|
#define NET_CHECKSUM_CUSTOM(Ser, x) \
|
||
|
|
{ \
|
||
|
|
SerializeChecksum(Ser,x, false); \
|
||
|
|
}
|
||
|
|
|
||
|
|
// There are cases where a checksum failure is expected, but we still need to eat the next word (just dont without erroring)
|
||
|
|
#define NET_CHECKSUM_IGNORE(Ser) \
|
||
|
|
{ \
|
||
|
|
uint32 Magic = 0; \
|
||
|
|
Ser << Magic; \
|
||
|
|
}
|
||
|
|
|
||
|
|
#else
|
||
|
|
|
||
|
|
// No ops in shipping builds
|
||
|
|
#define NET_CHECKSUM(Ser)
|
||
|
|
#define NET_CHECKSUM_IGNORE(Ser)
|
||
|
|
#define NET_CHECKSUM_CUSTOM(Ser, x)
|
||
|
|
#define NET_CHECKSUM_OR_END(ser)
|
||
|
|
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Values used for initializing UNetConnection and LanBeacon
|
||
|
|
*/
|
||
|
|
enum
|
||
|
|
{
|
||
|
|
MAX_PACKET_SIZE = 1024
|
||
|
|
}; // MTU for the connection
|
||
|
|
enum
|
||
|
|
{
|
||
|
|
LAN_BEACON_MAX_PACKET_SIZE = 1024
|
||
|
|
}; // MTU for the connection
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Functions to assist in detecting errors during RPC calls
|
||
|
|
*/
|
||
|
|
COREUOBJECT_API void RPC_ResetLastFailedReason();
|
||
|
|
COREUOBJECT_API void RPC_ValidateFailed(const TCHAR* Reason);
|
||
|
|
COREUOBJECT_API const TCHAR* RPC_GetLastFailedReason();
|