UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
FastArrayReplicationFragmentInternal.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
14
16
17namespace UE::Net
18{
19
20namespace FastArrayPollingPolicies
21{
22
33
34/*
35 * FNeedPollingPolicy, used for Native Iris FastArrays that does not need polling
36 */
38{
39public:
40 FPollingState* GetPollingState() { return &PollingState; }
41private:
42 FPollingState PollingState;
43};
44
45/*
46 * FNeedPollingPolicy, used for Native Iris FastArrays that do not require polling
47 */
49{
50public:
51 FPollingState* GetPollingState() { return nullptr; }
52};
53
54} // End of namespace FastArrayPollingPolicies
55
56namespace Private
57{
58
61{
63 template <typename FastArrayType, typename ItemArrayType>
64 static void ConditionalRebuildItemMap(FastArrayType& ArraySerializer, const ItemArrayType& Items, bool bForceRebuild);
65
67 template <typename FastArrayType, typename ItemArrayType>
69
72
75
78
81
86 template<typename FastArrayType>
95
96 template<typename FastArrayType>
98};
99
101{
102public:
104
105protected:
108
109 // FReplicationFragment Implementation
110 IRISCORE_API virtual void CollectOwner(FReplicationStateOwnerCollector* Owners) const override;
111
112protected:
113 // Get the ReplicationStateDescriptor for the FastArraySerializer Struct
115
116 // Get the ReplicationStateDescriptor for the Array Element
118
119 // Copy array element using the descriptor to esure that we only copy replicated data
121
122 // Compare an array element using the descriptor to ensure that we only compare replicated data
124
125 // Dequantize state into DstExternalBuffer, Note: it is expected to be initialized
127
128 // Partial dequantize state based on changemask into DstExternalBuffer, Note: it is expected to be initialized
130
131 // Dequantize additional properties to DstExternalBuffer, Note: it is expected to be initialized
133
134 // Dequantize and output state to string
135 IRISCORE_API static void ToString(FStringBuilderBase& StringBuilder, const uint8* ExternalStateBuffer, const FReplicationStateDescriptor* FastArrayPropertyDescriptor);
136
137protected:
138 // Replication descriptor built for the specific property
140
141 // This is the source state from which we source our state data
143
144 // Owner
146
147 // This allows us to quickly find the wrapped array relative to the owner
149};
150
151// Native FastArray
153{
154protected:
158 IRISCORE_API virtual void CollectOwner(FReplicationStateOwnerCollector* Owners) const override;
159
160 // Dequantize state into DstExternalBuffer, note it is expected to be initialized
162
163 IRISCORE_API static void ToString(FStringBuilderBase& StringBuilder, const uint8* ExternalStateBuffer, const FReplicationStateDescriptor* FastArrayPropertyDescriptor);
164
165protected:
166 // Replication descriptor built for the specific property
168
169 // Owner
171
172 // This allows us to quickly find the wrapped array relative to the owner
174};
175
176template <typename FastArrayType, typename ItemArrayType>
177void FFastArrayReplicationFragmentHelper::ConditionalRebuildItemMap(FastArrayType& ArraySerializer, const ItemArrayType& Items, bool bForceRebuild)
178{
179 typedef typename ItemArrayType::ElementType ItemType;
180
181 if (bForceRebuild || ArraySerializer.ItemMap.Num() != Items.Num())
182 {
183 UE_LOG(LogNetFastTArray, Verbose, TEXT("FastArrayDeltaSerialize: Recreating Items map. Items.Num: %d Map.Num: %d"), Items.Num(), ArraySerializer.ItemMap.Num());
184
185 ArraySerializer.ItemMap.Reset();
186
187 const ItemType* SrcItems = Items.GetData();
188 for (int32 It = 0, EndIt = Items.Num(); It != EndIt; ++It)
189 {
190 const ItemType& Item = SrcItems[It];
191 if (Item.ReplicationID == INDEX_NONE)
192 {
193 continue;
194 }
195
196 ArraySerializer.ItemMap.Add(Item.ReplicationID, It);
197 }
198 }
199}
200
201template <typename FastArrayType, typename ItemArrayType>
203{
204 typedef typename ItemArrayType::ElementType ItemType;
205
207
208 UE_LOG(LogNetFastTArray, Log, TEXT("FFastArrayReplicationFragmentHelper::ApplyReplicatedState for %s"), Context.Descriptor->DebugName->Name);
209
210 const uint32* ChangeMaskData = Context.StateBufferData.ChangeMaskData;
211 FNetBitArrayView MemberChangeMask = MakeNetBitArrayView(ChangeMaskData, Context.Descriptor->ChangeMaskBitCount);
212
213 // We currently use a simple modulo scheme for bits in the changemask
214 // A single bit might represent several entries in the array which all will be considered dirty, it is up to the serializer to handle this
215 // The first bit is used by the owning property we need to offset by one and deduct one from the usable bits
216 const FReplicationStateMemberChangeMaskDescriptor& MemberChangeMaskDescriptor = Context.Descriptor->MemberChangeMaskDescriptors[0];
219
220 // Force rebuild if the array has been modified
221 const bool bForceRebuildItemMap = MemberChangeMask.GetBit(0);
222
223 // We need to rebuild our maps for both target array and incoming data
224 // Can optimize this later
227
228 // We need this for callback
229 const int32 OriginalSize = DstWrappedArray->Num();
230
231 // Find removed elements in received data, that is elements that exist in old map but not in new map
233 {
235 ItemType* DstItems = DstWrappedArray->GetData();
236 for (int32 It=0, EndIt=DstWrappedArray->Num(); It != EndIt; ++It)
237 {
238 const int32 ReplicationID = DstItems[It].ReplicationID;
239 if (ReplicationID != -1 && !SrcArraySerializer->ItemMap.Contains(ReplicationID))
240 {
241 UE_LOG(LogNetFastTArray, Log, TEXT(" Removed ID: %d local Idx: %d"), ReplicationID, It);
242 RemovedIndices.Add(It);
243 }
244 }
245 }
246
247 // Find new and modified elements in received data, That is elements that do not exist in old map
250 {
252 ModifiedIndices.Reserve(SrcWrappedArray->Num());
253 const ItemType* SrcItems = SrcWrappedArray->GetData();
254 for (int32 It=0, EndIt=SrcWrappedArray->Num(); It != EndIt; ++It)
255 {
256 const bool bIsDirty = ChangeMaskBitCount == 0U || MemberChangeMask.GetBit((It % ChangeMaskBitCount) + ChangeMaskBitOffset);
257 if (!bIsDirty)
258 {
259 continue;
260 }
261
262 ItemType* DstItem = nullptr;
263 if (int32* ExistingIndex = DstArraySerializer->ItemMap.Find(SrcItems[It].ReplicationID))
264 {
265 // Only compare if the changemask indicate that this might be a dirty entry, the compare is required since we do share entries in the changemask.
267 {
268 UE_LOG(LogNetFastTArray, Log, TEXT(" Changed. ID: %d -> Idx: %d"), SrcItems[It].ReplicationID, *ExistingIndex);
269
271
272 // We use per element apply since we do not want to overwrite data that is not replicated
273 DstItem = &(*DstWrappedArray)[*ExistingIndex];
275 }
276 }
277 else
278 {
279 // Since we zero initialize our replicated properties we can end up with ReplicationID == 0 when receiving partial changes which should be ignored.
280 if (!(SrcItems[It].ReplicationID == INDEX_NONE || SrcItems[It].ReplicationID == 0))
281 {
283
284 UE_LOG(LogNetFastTArray, Log, TEXT(" New. ID: %d. New Element! local Idx: %d"), SrcItems[It].ReplicationID, AddedIndex);
285
286 // We need to propagate the ReplicationID in order to find our object
287 DstItem = &(*DstWrappedArray)[AddedIndex];
288 DstItem->ReplicationID = SrcItems[It].ReplicationID;
289
290 // should we store ids or indices?
292 }
293 }
294
295 if (DstItem != nullptr)
296 {
297 // Update the item's most recent array replication key
298 DstItem->MostRecentArrayReplicationKey = DstArraySerializer->ArrayReplicationKey;
299
300 // Update the item's replication key so that a client can re-serialize the array for client replay recording
301 DstItem->ReplicationKey++;
302 }
303 }
304 }
305
306 // Increment keys so that a client can re-serialize the array if needed, such as for client replay recording.
307 DstArraySerializer->IncrementArrayReplicationKey();
308
309 // Added and changed callbacks to FastArraySerializer
310 const int32 PreRemoveSize = DstWrappedArray->Num();
312
313 // Remove callback
315 {
316 (*DstWrappedArray)[RemovedIndex].PreReplicatedRemove(*DstArraySerializer);
317 }
318
319 // Remove callback to FastArraySerializer - done after adding new elements
321
322 if (PreRemoveSize != DstWrappedArray->Num())
323 {
324 UE_LOG(LogNetFastTArray, Error, TEXT("Item size changed after PreReplicatedRemove! PremoveSize: %d Item.Num: %d"),
326 }
327
328 // Add callbacks
330 {
331 (*DstWrappedArray)[AddedIndex].PostReplicatedAdd(*DstArraySerializer);
332 }
334
335 // Change callbacks
337 {
338 (*DstWrappedArray)[ExistingIndex].PostReplicatedChange(*DstArraySerializer);
339 }
341
342 if (PreRemoveSize != DstWrappedArray->Num())
343 {
344 UE_LOG(LogNetFastTArray, Error, TEXT("Item size changed after PostReplicatedAdd/PostReplicatedChange! PreRemoveSize: %d Item.Num: %d"),
346 }
347
348 // Remove indices
349 if (RemovedIndices.Num() > 0)
350 {
351 RemovedIndices.Sort();
352 for (int32 i = RemovedIndices.Num() - 1; i >= 0; --i)
353 {
355 if (DstWrappedArray->IsValidIndex(DeleteIndex))
356 {
358 }
359 }
360
361 // Clear the map now that the indices are all shifted around. This kind of sucks, we could use slightly better data structures here I think.
362 // This will force the ItemMap to be rebuilt for the current Items array
363 DstArraySerializer->ItemMap.Empty();
364 }
365
366 // Invoke PostReplicatedReceive if is defined by the serializer
367 CallPostReplicatedReceiveOrNot(*DstArraySerializer, OriginalSize, Context.bHasUnresolvableReferences);
368}
369
370}} // End of namespaces
constexpr auto MakeArrayView(OtherRangeType &&Other)
Definition ArrayView.h:873
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define RESTRICT
Definition Platform.h:706
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define CSV_SCOPED_TIMING_STAT(Category, StatName)
Definition CsvProfiler.h:150
#define CSV_DECLARE_CATEGORY_MODULE_EXTERN(Module_API, CategoryName)
Definition CsvProfiler.h:80
#define PRAGMA_ENABLE_DEPRECATION_WARNINGS
Definition GenericPlatformCompilerPreSetup.h:12
#define PRAGMA_DISABLE_DEPRECATION_WARNINGS
Definition GenericPlatformCompilerPreSetup.h:8
#define UE_LOG(CategoryName, Verbosity, Format,...)
Definition LogMacros.h:270
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Array.h:670
UE_FORCEINLINE_HINT void Reserve(SizeType Number)
Definition Array.h:3016
Definition EnableIf.h:20
Definition RefCounting.h:454
Definition UniquePtr.h:107
Definition ReplicationFragment.h:244
Definition NetBitArray.h:337
Definition NetSerializationContext.h:31
Definition ReplicationFragment.h:176
Definition ReplicationFragment.h:32
Definition FastArrayReplicationFragmentInternal.h:38
FPollingState * GetPollingState()
Definition FastArrayReplicationFragmentInternal.h:40
Definition FastArrayReplicationFragmentInternal.h:49
FPollingState * GetPollingState()
Definition FastArrayReplicationFragmentInternal.h:51
Definition FastArrayReplicationFragmentInternal.h:101
static IRISCORE_API void InternalDequantizeExtraProperties(FNetSerializationContext &Context, uint8 *RESTRICT DstExternalBuffer, const uint8 *RESTRICT SrcInternalBuffer, const FReplicationStateDescriptor *Descriptor)
Definition FastArrayReplicationFragment.cpp:183
static IRISCORE_API void InternalCopyArrayElement(const FReplicationStateDescriptor *ArrayElementDescriptor, void *RESTRICT Dst, const void *RESTRICT Src)
Definition FastArrayReplicationFragment.cpp:116
TRefCountPtr< const FReplicationStateDescriptor > ReplicationStateDescriptor
Definition FastArrayReplicationFragmentInternal.h:139
static IRISCORE_API void InternalDequantizeFastArray(FNetSerializationContext &Context, uint8 *RESTRICT DstExternalBuffer, const uint8 *RESTRICT SrcInternalBuffer, const FReplicationStateDescriptor *FastArrayPropertyDescriptor)
Definition FastArrayReplicationFragment.cpp:132
IRISCORE_API const FReplicationStateDescriptor * GetArrayElementDescriptor() const
Definition FastArrayReplicationFragment.cpp:103
IRISCORE_API const FReplicationStateDescriptor * GetFastArrayPropertyStructDescriptor() const
Definition FastArrayReplicationFragment.cpp:19
virtual IRISCORE_API void CollectOwner(FReplicationStateOwnerCollector *Owners) const override
Definition FastArrayReplicationFragment.cpp:213
static IRISCORE_API void ToString(FStringBuilderBase &StringBuilder, const uint8 *ExternalStateBuffer, const FReplicationStateDescriptor *FastArrayPropertyDescriptor)
Definition FastArrayReplicationFragment.cpp:218
TUniquePtr< FPropertyReplicationState > ReplicationState
Definition FastArrayReplicationFragmentInternal.h:142
static IRISCORE_API void InternalPartialDequantizeFastArray(FReplicationStateApplyContext &Context, uint8 *RESTRICT DstExternalBuffer, const uint8 *RESTRICT SrcInternalBuffer, const FReplicationStateDescriptor *FastArrayPropertyDescriptor)
Definition FastArrayReplicationFragment.cpp:154
UObject * Owner
Definition FastArrayReplicationFragmentInternal.h:145
SIZE_T WrappedArrayOffsetRelativeFastArraySerializerProperty
Definition FastArrayReplicationFragmentInternal.h:148
static IRISCORE_API bool InternalCompareArrayElement(const FReplicationStateDescriptor *ArrayElementDescriptor, void *RESTRICT Dst, const void *RESTRICT Src)
Definition FastArrayReplicationFragment.cpp:121
Definition FastArrayReplicationFragmentInternal.h:153
static IRISCORE_API void InternalDequantizeFastArray(FNetSerializationContext &Context, uint8 *RESTRICT DstExternalBuffer, const uint8 *RESTRICT SrcInternalBuffer, const FReplicationStateDescriptor *FastArrayPropertyDescriptor)
Definition FastArrayReplicationFragment.cpp:318
UObject * Owner
Definition FastArrayReplicationFragmentInternal.h:170
IRISCORE_API const FReplicationStateDescriptor * GetFastArrayPropertyStructDescriptor() const
Definition FastArrayReplicationFragment.cpp:250
IRISCORE_API const FReplicationStateDescriptor * GetArrayElementDescriptor() const
Definition FastArrayReplicationFragment.cpp:305
static IRISCORE_API void ToString(FStringBuilderBase &StringBuilder, const uint8 *ExternalStateBuffer, const FReplicationStateDescriptor *FastArrayPropertyDescriptor)
Definition FastArrayReplicationFragment.cpp:340
SIZE_T WrappedArrayOffsetRelativeFastArraySerializerProperty
Definition FastArrayReplicationFragmentInternal.h:173
virtual IRISCORE_API void CollectOwner(FReplicationStateOwnerCollector *Owners) const override
Definition FastArrayReplicationFragment.cpp:358
TRefCountPtr< const FReplicationStateDescriptor > ReplicationStateDescriptor
Definition FastArrayReplicationFragmentInternal.h:167
Definition Object.h:95
Definition OverriddenPropertySet.cpp:45
Definition NetworkVersion.cpp:28
EReplicationFragmentTraits
Definition ReplicationFragment.h:102
FNetBitArrayView MakeNetBitArrayView(const FNetBitArrayView::StorageWordType *Storage, uint32 BitCount)
Definition NetBitArray.h:1677
Definition FastArraySerializer.h:522
@ IrisFastArrayChangeMaskBitOffset
Definition IrisFastArraySerializer.h:30
Definition ReplicationFragment.h:66
Definition ReplicationStateDescriptor.h:199
Definition ReplicationStateDescriptor.h:77
uint16 BitOffset
Definition ReplicationStateDescriptor.h:78
Definition FastArrayReplicationFragmentInternal.h:27
int32 ReplicationID
Definition FastArrayReplicationFragmentInternal.h:29
int32 ReplicationKey
Definition FastArrayReplicationFragmentInternal.h:28
Definition FastArrayReplicationFragmentInternal.h:24
int32 ArrayReplicationKey
Definition FastArrayReplicationFragmentInternal.h:25
TArray< FEntry > ItemPollData
Definition FastArrayReplicationFragmentInternal.h:31
Definition FastArrayReplicationFragmentInternal.h:61
static void ConditionalRebuildItemMap(FastArrayType &ArraySerializer, const ItemArrayType &Items, bool bForceRebuild)
Definition FastArrayReplicationFragmentInternal.h:177
static TEnableIf<!TModels_V< FFastArraySerializer::CPostReplicatedReceiveFuncable, FastArrayType, constFFastArraySerializer::FPostReplicatedReceiveParameters & >, void >::Type CallPostReplicatedReceiveOrNot(FastArrayType &ArraySerializer, int32 OldArraySize, bool bHasUnresolvedReferences)
Definition FastArrayReplicationFragmentInternal.h:97
static IRISCORE_API bool InternalCompareArrayElement(const FReplicationStateDescriptor *ArrayElementDescriptor, void *RESTRICT Dst, const void *RESTRICT Src)
Definition FastArrayReplicationFragment.cpp:376
static TEnableIf< TModels_V< FFastArraySerializer::CPostReplicatedReceiveFuncable, FastArrayType, constFFastArraySerializer::FPostReplicatedReceiveParameters & >, void >::Type CallPostReplicatedReceiveOrNot(FastArrayType &ArraySerializer, int32 OldArraySize, bool bHasUnresolvedReferences)
Definition FastArrayReplicationFragmentInternal.h:87
static IRISCORE_API void InternalApplyArrayElement(const FReplicationStateDescriptor *ArrayElementDescriptor, void *RESTRICT Dst, const void *RESTRICT Src)
Definition FastArrayReplicationFragment.cpp:366
static IRISCORE_API void InternalCopyArrayElement(const FReplicationStateDescriptor *ArrayElementDescriptor, void *RESTRICT Dst, const void *RESTRICT Src)
Definition FastArrayReplicationFragment.cpp:371
static IRISCORE_API uint32 GetFastArrayStructItemArrayMemberIndex(const FReplicationStateDescriptor *StructDescriptor)
Definition FastArrayReplicationFragment.cpp:236
static void ApplyReplicatedState(FastArrayType *DstFastArray, ItemArrayType *DstWrappedArray, FastArrayType *SrcFastArray, const ItemArrayType *SrcWrappedArray, const FReplicationStateDescriptor *ArrayElementDescriptor, FReplicationStateApplyContext &Context)
Definition FastArrayReplicationFragmentInternal.h:202