mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
Thank you logic teacher (rep is almost done)
This commit is contained in:
@@ -12,6 +12,97 @@ class TBitArray;
|
||||
template<typename Allocator = FDefaultBitArrayAllocator>
|
||||
class TConstSetBitIterator;
|
||||
|
||||
class FBitReference
|
||||
{
|
||||
public:
|
||||
|
||||
FORCEINLINE FBitReference(uint32& InData, uint32 InMask)
|
||||
: Data(InData)
|
||||
, Mask(InMask)
|
||||
{}
|
||||
|
||||
FORCEINLINE operator bool() const
|
||||
{
|
||||
return (Data & Mask) != 0;
|
||||
}
|
||||
FORCEINLINE void operator=(const bool NewValue)
|
||||
{
|
||||
if (NewValue)
|
||||
{
|
||||
Data |= Mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data &= ~Mask;
|
||||
}
|
||||
}
|
||||
/*
|
||||
FORCEINLINE void AtomicSet(const bool NewValue)
|
||||
{
|
||||
if (NewValue)
|
||||
{
|
||||
if (!(Data & Mask))
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
uint32 Current = Data;
|
||||
uint32 Desired = Current | Mask;
|
||||
if (Current == Desired || FPlatformAtomics::InterlockedCompareExchange((volatile int32*)&Data, (int32)Desired, (int32)Current) == (int32)Current)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Data & Mask)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
uint32 Current = Data;
|
||||
uint32 Desired = Current & ~Mask;
|
||||
if (Current == Desired || FPlatformAtomics::InterlockedCompareExchange((volatile int32*)&Data, (int32)Desired, (int32)Current) == (int32)Current)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
FORCEINLINE FBitReference& operator=(const FBitReference& Copy)
|
||||
{
|
||||
// As this is emulating a reference, assignment should not rebind,
|
||||
// it should write to the referenced bit.
|
||||
*this = (bool)Copy;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32& Data;
|
||||
uint32 Mask;
|
||||
};
|
||||
|
||||
class FConstBitReference
|
||||
{
|
||||
public:
|
||||
|
||||
FORCEINLINE FConstBitReference(const uint32& InData, uint32 InMask)
|
||||
: Data(InData)
|
||||
, Mask(InMask)
|
||||
{}
|
||||
|
||||
FORCEINLINE operator bool() const
|
||||
{
|
||||
return (Data & Mask) != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint32& Data;
|
||||
uint32 Mask;
|
||||
};
|
||||
|
||||
template<typename Allocator /*= FDefaultBitArrayAllocator*/>
|
||||
class TBitArray
|
||||
{
|
||||
@@ -36,6 +127,23 @@ public:
|
||||
*this = Copy;
|
||||
}
|
||||
|
||||
FORCEINLINE FBitReference operator[](int32 Index)
|
||||
{
|
||||
// check(Index >= 0 && Index < NumBits);
|
||||
return FBitReference(
|
||||
GetData()[Index / NumBitsPerDWORD],
|
||||
1 << (Index & (NumBitsPerDWORD - 1))
|
||||
);
|
||||
}
|
||||
FORCEINLINE const FConstBitReference operator[](int32 Index) const
|
||||
{
|
||||
// check(Index >= 0 && Index < NumBits);
|
||||
return FConstBitReference(
|
||||
GetData()[Index / NumBitsPerDWORD],
|
||||
1 << (Index & (NumBitsPerDWORD - 1))
|
||||
);
|
||||
}
|
||||
|
||||
FORCEINLINE const uint32* GetData() const
|
||||
{
|
||||
return (uint32*)AllocatorInstance.GetAllocation();
|
||||
|
||||
17
Project Reboot 3.0/CoreNet.h
Normal file
17
Project Reboot 3.0/CoreNet.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "inc.h"
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
9
Project Reboot 3.0/IsTriviallyDestructible.h
Normal file
9
Project Reboot 3.0/IsTriviallyDestructible.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
template <typename T>
|
||||
struct TIsTriviallyDestructible
|
||||
{
|
||||
enum { Value = std::is_trivially_destructible_v<T> };
|
||||
};
|
||||
@@ -83,4 +83,4 @@ inline uint32 GetTypeHash(const FName N)
|
||||
return N.ComparisonIndex.Value + N.GetNumber();
|
||||
}
|
||||
|
||||
#define NAME_None FName(0);
|
||||
#define NAME_None FName(0)
|
||||
@@ -79,11 +79,11 @@ public:
|
||||
return Get<double>(LastReceiveTimeOffset);
|
||||
}
|
||||
|
||||
/* TSet<FName>& GetClientVisibleLevelNames()
|
||||
TSet<FName>& GetClientVisibleLevelNames()
|
||||
{
|
||||
static auto ClientVisibleLevelNamesOffset = 0x336C8;
|
||||
return *(TSet<FName>*)(__int64(this) + ClientVisibleLevelNamesOffset);
|
||||
} */
|
||||
}
|
||||
|
||||
class UNetDriver*& GetDriver()
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <random>
|
||||
#include "Package.h"
|
||||
#include "AssertionMacros.h"
|
||||
#include "CoreNet.h"
|
||||
#include "ChildConnection.h"
|
||||
#include "bots.h"
|
||||
#include "NetworkingDistanceConstants.h"
|
||||
@@ -131,13 +132,6 @@ bool UNetDriver::IsLevelInitializedForActor(const AActor* InActor, const UNetCon
|
||||
return true;
|
||||
}
|
||||
|
||||
/* #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) // (Milxnor) This is on some ue versions and others not.
|
||||
if (!InActor || !InConnection)
|
||||
return false;
|
||||
|
||||
// check(World == InActor->GetWorld());
|
||||
#endif */
|
||||
|
||||
bool bFirstWorldCheck = Engine_Version == 416
|
||||
? (InConnection->GetClientWorldPackageName() == GetWorld()->GetOutermost()->GetFName())
|
||||
: (InConnection->GetClientWorldPackageName() == GetWorldPackage()->NamePrivate);
|
||||
@@ -155,7 +149,7 @@ FNetViewer::FNetViewer(UNetConnection* InConnection, float DeltaSeconds) :
|
||||
ViewDir(ForceInit)
|
||||
{
|
||||
if (!InConnection->GetOwningActor()) return;
|
||||
if (InConnection->GetPlayerController() || (InConnection->GetPlayerController() != InConnection->GetOwningActor())) return;
|
||||
if (InConnection->GetPlayerController() && (InConnection->GetPlayerController() != InConnection->GetOwningActor())) return;
|
||||
|
||||
APlayerController* ViewingController = InConnection->GetPlayerController();
|
||||
|
||||
@@ -163,7 +157,7 @@ FNetViewer::FNetViewer(UNetConnection* InConnection, float DeltaSeconds) :
|
||||
if (ViewingController)
|
||||
{
|
||||
FRotator ViewRotation = ViewingController->GetControlRotation();
|
||||
ViewingController->GetActorEyesViewPoint(&ViewLocation, &ViewRotation); // T(REP)
|
||||
ViewingController->GetActorEyesViewPoint(&ViewLocation, &ViewRotation);
|
||||
ViewDir = ViewRotation.Vector();
|
||||
}
|
||||
}
|
||||
@@ -542,6 +536,58 @@ int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connect
|
||||
return FinalSortedCount;
|
||||
}
|
||||
|
||||
using FArchive = void;
|
||||
|
||||
__declspec(noinline) void SetChannelActorForDestroy(UActorChannel* Channel, FActorDestructionInfo* DestructInfo)
|
||||
{
|
||||
auto Connection = Channel->GetConnection();
|
||||
|
||||
// check(Connection->Channels[ChIndex]==Channel);
|
||||
|
||||
if (
|
||||
true
|
||||
// T(REP)
|
||||
)
|
||||
{
|
||||
|
||||
// You can get size by searching "Making partial bunch from content bunch. bitsThisBunch: %d bitsLeft: %d", there is a new call.
|
||||
struct FOutBunch
|
||||
{
|
||||
char pad[0x110];
|
||||
};
|
||||
|
||||
LOG_INFO(LogDev, "SetChannelActorForDestroy PathName: {}", DestructInfo->PathName.ToString());
|
||||
|
||||
FOutBunch(*ConstructorFOutBunch)(FOutBunch*, UChannel*, bool) = decltype(ConstructorFOutBunch)(__int64(GetModuleHandleW(0)) + 0x194E800);
|
||||
FOutBunch CloseBunch{};
|
||||
auto Helloooo = ConstructorFOutBunch(&CloseBunch, Channel, 1);
|
||||
// check(!CloseBunch.IsError());
|
||||
// check(CloseBunch.bClose);
|
||||
|
||||
LOG_INFO(LogDev, "Called Constructor!");
|
||||
|
||||
// https://imgur.com/a/EtKFkrD
|
||||
|
||||
*(bool*)(__int64(&CloseBunch) + 0xE8) = 1; // bReliable
|
||||
*(bool*)(__int64(&CloseBunch) + 0xE6) = 0; // bDormant
|
||||
|
||||
// NET_CHECKSUM(CloseBunch); // This is to mirror the Checksum in UPackageMapClient::SerializeNewActor
|
||||
|
||||
using UPackageMap = UObject;
|
||||
|
||||
reinterpret_cast<bool(*)(UPackageMap*,
|
||||
// FArchive& Ar,
|
||||
FOutBunch& Ar,
|
||||
UObject* InOuter, FNetworkGUID NetGUID, FString ObjName)>(Connection->GetPackageMap()->VFTable[0x238 / 8])
|
||||
(Connection->GetPackageMap(), CloseBunch, DestructInfo->ObjOuter.Get(), DestructInfo->NetGUID, DestructInfo->PathName); // WriteObject
|
||||
|
||||
// 0x196E9C0
|
||||
reinterpret_cast<FPacketIdRange(*)(UActorChannel*, FOutBunch*, bool)>(Channel->VFTable[0x288 / 8])(Channel, &CloseBunch, false); // SendBunch
|
||||
|
||||
// TODO FARCHIVE::~FARHCIVE
|
||||
}
|
||||
}
|
||||
|
||||
int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, std::vector<FActorPriority*>& PriorityActors, const int32 FinalSortedCount, int32& OutUpdated)
|
||||
{
|
||||
int32 ActorUpdatesThisConnection = 0;
|
||||
@@ -557,12 +603,11 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
||||
{
|
||||
FNetworkObjectInfo* ActorInfo = PriorityActors[j]->ActorInfo;
|
||||
|
||||
// Deletion entry
|
||||
if (ActorInfo == NULL && PriorityActors[j]->DestructionInfo)
|
||||
{
|
||||
/*
|
||||
if (PriorityActors[j]->DestructionInfo->StreamingLevelName != NAME_None &&
|
||||
!Connection->GetClientVisibleLevelNames().Contains(PriorityActors[j]->DestructionInfo->StreamingLevelName)
|
||||
if (PriorityActors[j]->DestructionInfo->StreamingLevelName != NAME_None
|
||||
&& !Connection->GetClientVisibleLevelNames().Contains(PriorityActors[j]->DestructionInfo->StreamingLevelName)
|
||||
)
|
||||
{
|
||||
continue;
|
||||
@@ -573,7 +618,7 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
||||
{
|
||||
FinalRelevantCount++;
|
||||
|
||||
Channel->SetChannelActorForDestroy(PriorityActors[j]->DestructionInfo);
|
||||
SetChannelActorForDestroy(Channel, PriorityActors[j]->DestructionInfo);
|
||||
Connection->GetDestroyedStartupOrDormantActors().Remove(PriorityActors[j]->DestructionInfo->NetGUID);
|
||||
}
|
||||
|
||||
@@ -621,6 +666,7 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
||||
Channel = (UActorChannel*)Connection->CreateChannel(CHTYPE_Actor, 1, EChannelCreateFlags::OpenedLocally);
|
||||
if (Channel)
|
||||
{
|
||||
LOG_INFO(LogDev, "Replicating: {}", Actor->GetFullName());
|
||||
Channel->SetChannelActor(Actor, ESetChannelActorFlags::None1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,6 +315,7 @@
|
||||
<ClInclude Include="ContainerAllocationPolicies.h" />
|
||||
<ClInclude Include="Controller.h" />
|
||||
<ClInclude Include="builder.h" />
|
||||
<ClInclude Include="CoreNet.h" />
|
||||
<ClInclude Include="CurveTable.h" />
|
||||
<ClInclude Include="DataTable.h" />
|
||||
<ClInclude Include="DataTableFunctionLibrary.h" />
|
||||
@@ -431,6 +432,7 @@
|
||||
<ClInclude Include="IsPODType.h" />
|
||||
<ClInclude Include="IsPointer.h" />
|
||||
<ClInclude Include="IsTriviallyCopyConstructible.h" />
|
||||
<ClInclude Include="IsTriviallyDestructible.h" />
|
||||
<ClInclude Include="KismetMathLibrary.h" />
|
||||
<ClInclude Include="KismetStringLibrary.h" />
|
||||
<ClInclude Include="KismetSystemLibrary.h" />
|
||||
|
||||
@@ -999,6 +999,12 @@
|
||||
<ClInclude Include="NetworkingDistanceConstants.h">
|
||||
<Filter>Engine\Source\Runtime\Engine\Public</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CoreNet.h">
|
||||
<Filter>Engine\Source\Runtime\CoreUObject\Public\UObject</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="IsTriviallyDestructible.h">
|
||||
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Engine">
|
||||
|
||||
@@ -5,38 +5,9 @@
|
||||
#include "SparseArray.h"
|
||||
#include "ChooseClass.h"
|
||||
#include "UnrealTypeTraits.h"
|
||||
#include "UnrealTemplate.h"
|
||||
|
||||
template <typename ElementType>
|
||||
class TSetElement
|
||||
{
|
||||
public:
|
||||
ElementType Value;
|
||||
mutable int32 HashNextId;
|
||||
mutable int32 HashIndex;
|
||||
|
||||
TSetElement(ElementType InValue, int32 InHashNextId, int32 InHashIndex)
|
||||
: Value(InValue)
|
||||
, HashNextId(InHashNextId)
|
||||
, HashIndex(InHashIndex)
|
||||
{
|
||||
}
|
||||
|
||||
FORCEINLINE TSetElement<ElementType>& operator=(const TSetElement<ElementType>& Other)
|
||||
{
|
||||
Value = Other.Value;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const TSetElement& Other) const
|
||||
{
|
||||
return Value == Other.Value;
|
||||
}
|
||||
FORCEINLINE bool operator!=(const TSetElement& Other) const
|
||||
{
|
||||
return Value != Other.Value;
|
||||
}
|
||||
};
|
||||
|
||||
/** Either NULL or an identifier for an element of a set. */
|
||||
class FSetElementId
|
||||
{
|
||||
public:
|
||||
@@ -90,6 +61,45 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename InElementType>
|
||||
class TSetElement
|
||||
{
|
||||
public:
|
||||
typedef InElementType ElementType;
|
||||
|
||||
ElementType Value;
|
||||
mutable FSetElementId HashNextId;
|
||||
mutable int32 HashIndex;
|
||||
|
||||
FORCEINLINE TSetElement()
|
||||
{}
|
||||
|
||||
/** Initialization constructor. */
|
||||
// template <typename InitType, typename = typename TEnableIf<!TAreTypesEqual<TSetElement, typename TDecay<InitType>::Type>::Value>::Type> explicit FORCEINLINE TSetElement(InitType&& InValue) : Value/////(Forward<InitType>(InValue)) {} // T(R)
|
||||
|
||||
FORCEINLINE TSetElement(const TSetElement& Rhs) : Value(Rhs.Value), HashNextId(Rhs.HashNextId), HashIndex(Rhs.HashIndex) {}
|
||||
FORCEINLINE TSetElement(TSetElement&& Rhs) : Value(MoveTempIfPossible(Rhs.Value)), HashNextId(MoveTemp(Rhs.HashNextId)), HashIndex(Rhs.HashIndex) {}
|
||||
|
||||
FORCEINLINE TSetElement& operator=(const TSetElement& Rhs) { Value = Rhs.Value; HashNextId = Rhs.HashNextId; HashIndex = Rhs.HashIndex; return *this; }
|
||||
FORCEINLINE TSetElement& operator=(TSetElement&& Rhs) { Value = MoveTempIfPossible(Rhs.Value); HashNextId = MoveTemp(Rhs.HashNextId); HashIndex = Rhs.HashIndex; return *this; }
|
||||
|
||||
/*
|
||||
FORCEINLINE friend FArchive & operator<<(FArchive & Ar, TSetElement & Element)
|
||||
{
|
||||
return Ar << Element.Value;
|
||||
}
|
||||
*/
|
||||
|
||||
FORCEINLINE bool operator==(const TSetElement& Other) const
|
||||
{
|
||||
return Value == Other.Value;
|
||||
}
|
||||
FORCEINLINE bool operator!=(const TSetElement& Other) const
|
||||
{
|
||||
return Value != Other.Value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ElementType, typename InKeyType, bool bInAllowDuplicateKeys = false>
|
||||
struct BaseKeyFuncs
|
||||
{
|
||||
@@ -152,6 +162,9 @@ private:
|
||||
public:
|
||||
typedef typename KeyFuncs::KeyInitType KeyInitType;
|
||||
typedef typename KeyFuncs::ElementInitType ElementInitType;
|
||||
// using SizeType = typename Allocator::SparseArrayAllocator::ElementAllocator::SizeType; // Milxnor: Bruh idk
|
||||
using SizeType = int32;
|
||||
static_assert(std::is_same_v<SizeType, int32>, "TSet currently only supports 32-bit allocators");
|
||||
|
||||
typedef TSetElement<InElementType> SetElementType;
|
||||
|
||||
@@ -170,7 +183,82 @@ public:
|
||||
return ((FSetElementId*)Hash.GetAllocation())[HashIndex & (HashSize - 1)];
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename ComparableKey>
|
||||
FORCEINLINE int32 RemoveImpl(uint32 KeyHash, const ComparableKey& Key)
|
||||
{
|
||||
int32 NumRemovedElements = 0;
|
||||
|
||||
FSetElementId* NextElementId = &GetTypedHash(KeyHash);
|
||||
while (NextElementId->IsValidId())
|
||||
{
|
||||
SetElementType& Element = Elements[NextElementId->Index];
|
||||
|
||||
if (KeyFuncs::Matches(KeyFuncs::GetSetKey(Element.Value), Key))
|
||||
{
|
||||
// This element matches the key, remove it from the set. Note that Remove sets *NextElementId to point to the next
|
||||
// element after the removed element in the hash bucket.
|
||||
RemoveByIndex(NextElementId->Index);
|
||||
NumRemovedElements++;
|
||||
|
||||
if (!KeyFuncs::bAllowDuplicateKeys)
|
||||
{
|
||||
// If the hash disallows duplicate keys, we're done removing after the first matched key.
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NextElementId = &Element.HashNextId;
|
||||
}
|
||||
}
|
||||
|
||||
return NumRemovedElements;
|
||||
}
|
||||
|
||||
public:
|
||||
void RemoveByIndex(SizeType ElementIndex)
|
||||
{
|
||||
// checkf(Elements.IsValidIndex(ElementIndex), TEXT("Invalid ElementIndex passed to TSet::RemoveByIndex"));
|
||||
|
||||
const SetElementType& ElementBeingRemoved = Elements[ElementIndex];
|
||||
|
||||
// Remove the element from the hash.
|
||||
FSetElementId* HashPtr = Hash.GetAllocation();
|
||||
SizeType* NextElementIndexIter = &HashPtr[ElementBeingRemoved.HashIndex].Index;
|
||||
for (;;)
|
||||
{
|
||||
SizeType NextElementIndex = *NextElementIndexIter;
|
||||
// checkf(NextElementIndex != INDEX_NONE, TEXT("Corrupt hash"));
|
||||
|
||||
if (NextElementIndex == ElementIndex)
|
||||
{
|
||||
*NextElementIndexIter = ElementBeingRemoved.HashNextId.Index;
|
||||
break;
|
||||
}
|
||||
|
||||
NextElementIndexIter = &Elements[NextElementIndex].HashNextId.Index;
|
||||
}
|
||||
|
||||
// Remove the element from the elements array.
|
||||
Elements.RemoveAt(ElementIndex);
|
||||
}
|
||||
|
||||
void Remove(FSetElementId ElementId)
|
||||
{
|
||||
RemoveByIndex(ElementId.Index);
|
||||
}
|
||||
|
||||
int32 Remove(KeyInitType Key)
|
||||
{
|
||||
if (Elements.Num())
|
||||
{
|
||||
return RemoveImpl(KeyFuncs::GetKeyHash(Key), Key);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FORCEINLINE ElementType* Find(KeyInitType Key)
|
||||
{
|
||||
FSetElementId ElementId = FindId(Key);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "ChooseClass.h"
|
||||
#include "log.h"
|
||||
#include "TypeCompatibleBytes.h"
|
||||
#include "IsTriviallyDestructible.h"
|
||||
|
||||
#define INDEX_NONE -1
|
||||
|
||||
@@ -53,6 +54,42 @@ public:
|
||||
{
|
||||
return Data.Num() - NumFreeIndices;
|
||||
}
|
||||
void RemoveAt(int32 Index, int32 Count = 1)
|
||||
{
|
||||
if (!TIsTriviallyDestructible<ElementType>::Value)
|
||||
{
|
||||
for (int32 It = Index, ItCount = Count; ItCount; ++It, --ItCount)
|
||||
{
|
||||
((ElementType&)GetData(It).ElementData).~ElementType();
|
||||
}
|
||||
}
|
||||
|
||||
RemoveAtUninitialized(Index, Count);
|
||||
}
|
||||
|
||||
/** Removes Count elements from the array, starting from Index, without destructing them. */
|
||||
void RemoveAtUninitialized(int32 Index, int32 Count = 1)
|
||||
{
|
||||
for (; Count; --Count)
|
||||
{
|
||||
// check(AllocationFlags[Index]);
|
||||
|
||||
// Mark the element as free and add it to the free element list.
|
||||
if (NumFreeIndices)
|
||||
{
|
||||
GetData(FirstFreeIndex).PrevFreeIndex = Index;
|
||||
}
|
||||
auto& IndexData = GetData(Index);
|
||||
IndexData.PrevFreeIndex = -1;
|
||||
IndexData.NextFreeIndex = NumFreeIndices > 0 ? FirstFreeIndex : INDEX_NONE;
|
||||
FirstFreeIndex = Index;
|
||||
++NumFreeIndices;
|
||||
AllocationFlags[Index] = false;
|
||||
|
||||
++Index;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool bConst>
|
||||
class TBaseIterator
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user