mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 10:52:22 +01:00
Dude 💀
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "reboot.h"
|
#include "reboot.h"
|
||||||
#include "GameplayStatics.h"
|
#include "GameplayStatics.h"
|
||||||
|
#include "Level.h"
|
||||||
|
|
||||||
bool AActor::HasAuthority()
|
bool AActor::HasAuthority()
|
||||||
{
|
{
|
||||||
@@ -11,6 +12,11 @@ bool AActor::HasAuthority()
|
|||||||
return Get<uint8_t>(RoleOffset) == 3;
|
return Get<uint8_t>(RoleOffset) == 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AActor::GetNetDormancy(const FVector& ViewPos, const FVector& ViewDir, AActor* Viewer, AActor* ViewTarget, class UActorChannel* InChannel, float Time, bool bLowBandwidth) // T(REP)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool AActor::IsTearOff()
|
bool AActor::IsTearOff()
|
||||||
{
|
{
|
||||||
static auto bTearOffOffset = GetOffset("bTearOff");
|
static auto bTearOffOffset = GetOffset("bTearOff");
|
||||||
@@ -18,7 +24,12 @@ bool AActor::IsTearOff()
|
|||||||
return ReadBitfieldValue(bTearOffOffset, bTearOffFieldMask);
|
return ReadBitfieldValue(bTearOffOffset, bTearOffFieldMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FORCEINLINE */ ENetDormancy& AActor::GetNetDormancy()
|
ULevel* AActor::GetLevel() const
|
||||||
|
{
|
||||||
|
return GetTypedOuter<ULevel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FORCEINLINE */ ENetDormancy& AActor::NetDormancy()
|
||||||
{
|
{
|
||||||
static auto NetDormancyOffset = GetOffset("NetDormancy");
|
static auto NetDormancyOffset = GetOffset("NetDormancy");
|
||||||
return Get<ENetDormancy>(NetDormancyOffset);
|
return Get<ENetDormancy>(NetDormancyOffset);
|
||||||
@@ -38,15 +49,6 @@ FTransform AActor::GetTransform()
|
|||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
UWorld* AActor::GetWorld()
|
|
||||||
{
|
|
||||||
return GetWorld(); // for real
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
void AActor::SetNetDormancy(ENetDormancy Dormancy)
|
void AActor::SetNetDormancy(ENetDormancy Dormancy)
|
||||||
{
|
{
|
||||||
static auto SetNetDormancyFn = FindObject<UFunction>(L"/Script/Engine.Actor.SetNetDormancy");
|
static auto SetNetDormancyFn = FindObject<UFunction>(L"/Script/Engine.Actor.SetNetDormancy");
|
||||||
@@ -63,6 +65,18 @@ AActor* AActor::GetOwner()
|
|||||||
return Owner;
|
return Owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FName& AActor::GetNetDriverName()
|
||||||
|
{
|
||||||
|
static auto NetDriverNameOffset = GetOffset("NetDriverName");
|
||||||
|
return Get<FName>(NetDriverNameOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
ENetRole& AActor::GetRemoteRole()
|
||||||
|
{
|
||||||
|
static auto RemoteRoleOffset = GetOffset("RemoteRole");
|
||||||
|
return Get<ENetRole>(RemoteRoleOffset);
|
||||||
|
}
|
||||||
|
|
||||||
void AActor::K2_DestroyActor()
|
void AActor::K2_DestroyActor()
|
||||||
{
|
{
|
||||||
static auto DestroyActorFn = FindObject<UFunction>("/Script/Engine.Actor.K2_DestroyActor");
|
static auto DestroyActorFn = FindObject<UFunction>("/Script/Engine.Actor.K2_DestroyActor");
|
||||||
@@ -195,12 +209,12 @@ void AActor::ForceNetUpdate()
|
|||||||
this->ProcessEvent(ForceNetUpdateFn);
|
this->ProcessEvent(ForceNetUpdateFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AActor::IsNetStartupActor()
|
bool AActor::IsNetStartupActor() // T(REP)
|
||||||
{
|
{
|
||||||
return IsNetStartup(); // The implementation on this function depends on the version.
|
return IsNetStartup(); // The implementation on this function depends on the version.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AActor::IsPendingKillPending()
|
bool AActor::IsPendingKillPending() // T(REP)
|
||||||
{
|
{
|
||||||
return IsActorBeingDestroyed() || !IsValidChecked(this);
|
return IsActorBeingDestroyed() || !IsValidChecked(this);
|
||||||
}
|
}
|
||||||
@@ -246,6 +260,11 @@ const AActor* AActor::GetNetOwner() const
|
|||||||
return GetNetOwnerOriginal(this);
|
return GetNetOwnerOriginal(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AActor::IsActorInitialized() // T(REP)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void AActor::GetActorEyesViewPoint(FVector* OutLocation, FRotator* OutRotation) const
|
void AActor::GetActorEyesViewPoint(FVector* OutLocation, FRotator* OutRotation) const
|
||||||
{
|
{
|
||||||
static auto GetActorEyesViewPointFn = FindObject<UFunction>(L"/Script/Engine.Actor.GetActorEyesViewPoint");
|
static auto GetActorEyesViewPointFn = FindObject<UFunction>(L"/Script/Engine.Actor.GetActorEyesViewPoint");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "anticheat.h"
|
#include "anticheat.h"
|
||||||
|
#include "Vector.h"
|
||||||
|
|
||||||
enum class ENetDormancy : uint8_t
|
enum class ENetDormancy : uint8_t
|
||||||
{
|
{
|
||||||
@@ -17,15 +18,19 @@ enum class ENetDormancy : uint8_t
|
|||||||
class AActor : public UObject
|
class AActor : public UObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static inline void (*originalCallPreReplication)(AActor*, class UNetDriver*);
|
||||||
struct FTransform GetTransform();
|
struct FTransform GetTransform();
|
||||||
|
|
||||||
// class UWorld* GetWorld();
|
bool GetNetDormancy(const FVector& ViewPos, const FVector& ViewDir, AActor* Viewer, AActor* ViewTarget, class UActorChannel* InChannel, float Time, bool bLowBandwidth);
|
||||||
bool HasAuthority();
|
bool HasAuthority();
|
||||||
bool IsTearOff();
|
bool IsTearOff();
|
||||||
/* FORCEINLINE */ ENetDormancy& GetNetDormancy();
|
class ULevel* GetLevel() const;
|
||||||
|
/* FORCEINLINE */ ENetDormancy& NetDormancy();
|
||||||
int32& GetNetTag();
|
int32& GetNetTag();
|
||||||
void SetNetDormancy(ENetDormancy Dormancy);
|
void SetNetDormancy(ENetDormancy Dormancy);
|
||||||
AActor* GetOwner();
|
AActor* GetOwner();
|
||||||
|
FName& GetNetDriverName();
|
||||||
|
ENetRole& GetRemoteRole();
|
||||||
struct FVector GetActorScale3D();
|
struct FVector GetActorScale3D();
|
||||||
struct FVector GetActorLocation();
|
struct FVector GetActorLocation();
|
||||||
struct FVector GetActorForwardVector();
|
struct FVector GetActorForwardVector();
|
||||||
@@ -52,12 +57,12 @@ public:
|
|||||||
float& GetNetUpdateFrequency();
|
float& GetNetUpdateFrequency();
|
||||||
float& GetMinNetUpdateFrequency();
|
float& GetMinNetUpdateFrequency();
|
||||||
const AActor* GetNetOwner() const;
|
const AActor* GetNetOwner() const;
|
||||||
|
bool IsActorInitialized();
|
||||||
void GetActorEyesViewPoint(FVector* OutLocation, FRotator* OutRotation) const;
|
void GetActorEyesViewPoint(FVector* OutLocation, FRotator* OutRotation) const;
|
||||||
AActor* GetClosestActor(UClass* ActorClass, float DistMax, std::function<bool(AActor*)> AdditionalCheck = [&](AActor*) { return true; });
|
AActor* GetClosestActor(UClass* ActorClass, float DistMax, std::function<bool(AActor*)> AdditionalCheck = [&](AActor*) { return true; });
|
||||||
|
|
||||||
bool IsRelevancyOwnerFor(const AActor* ReplicatedActor, const AActor* ActorOwner, const AActor* ConnectionActor) const
|
bool IsRelevancyOwnerFor(const AActor* ReplicatedActor, const AActor* ActorOwner, const AActor* ConnectionActor) const // T(REP)
|
||||||
{
|
{
|
||||||
// we should call virtual function but eh
|
|
||||||
// return (ActorOwner == this);
|
// return (ActorOwner == this);
|
||||||
|
|
||||||
static auto IsRelevancyOwnerForOffset = 0x428;
|
static auto IsRelevancyOwnerForOffset = 0x428;
|
||||||
|
|||||||
@@ -3,9 +3,29 @@
|
|||||||
#include "Channel.h"
|
#include "Channel.h"
|
||||||
#include "NetworkGuid.h"
|
#include "NetworkGuid.h"
|
||||||
|
|
||||||
|
enum ESetChannelActorFlags
|
||||||
|
{
|
||||||
|
None1 = 0, // Bro compiler what
|
||||||
|
SkipReplicatorCreation = (1 << 0),
|
||||||
|
SkipMarkActive = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
class UActorChannel : public UChannel
|
class UActorChannel : public UChannel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static inline void (*originalSetChannelActor)(UActorChannel*, AActor*);
|
||||||
|
static inline __int64 (*originalReplicateActor)(UActorChannel*);
|
||||||
|
|
||||||
|
void SetChannelActor(AActor* Actor, ESetChannelActorFlags Flags)
|
||||||
|
{
|
||||||
|
originalSetChannelActor(this, Actor); // T(REP) ADD FLAGS FOR NEWER BUILDS
|
||||||
|
}
|
||||||
|
|
||||||
|
__int64 ReplicateActor() // Returns how many bits were replicated (does not include non-bunch packet overhead)
|
||||||
|
{
|
||||||
|
return originalReplicateActor(this);
|
||||||
|
}
|
||||||
|
|
||||||
double& GetLastUpdateTime()
|
double& GetLastUpdateTime()
|
||||||
{
|
{
|
||||||
static auto LastUpdateTimeOffset = GetOffset("Actor") + 8 + 4 + 4 + 8; // checked on 4.19
|
static auto LastUpdateTimeOffset = GetOffset("Actor") + 8 + 4 + 4 + 8; // checked on 4.19
|
||||||
|
|||||||
@@ -5,17 +5,7 @@
|
|||||||
|
|
||||||
#include "MemoryOps.h"
|
#include "MemoryOps.h"
|
||||||
#include "ContainerAllocationPolicies.h"
|
#include "ContainerAllocationPolicies.h"
|
||||||
|
#include "IsPointer.h"
|
||||||
struct FMemory
|
|
||||||
{
|
|
||||||
static inline void* (*Realloc)(void* Original, SIZE_T Count, uint32_t Alignment /* = DEFAULT_ALIGNMENT */);
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T = __int64>
|
|
||||||
static T* AllocUnreal(size_t Size)
|
|
||||||
{
|
|
||||||
return (T*)FMemory::Realloc(0, Size, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename InElementType> //, typename InAllocatorType>
|
template<typename InElementType> //, typename InAllocatorType>
|
||||||
class TArray
|
class TArray
|
||||||
@@ -26,6 +16,7 @@ public:
|
|||||||
|
|
||||||
using ElementAllocatorType = InElementType*;
|
using ElementAllocatorType = InElementType*;
|
||||||
using SizeType = int32;
|
using SizeType = int32;
|
||||||
|
typedef InElementType ElementType;
|
||||||
|
|
||||||
ElementAllocatorType Data = nullptr; // AllocatorInstance;
|
ElementAllocatorType Data = nullptr; // AllocatorInstance;
|
||||||
SizeType ArrayNum;
|
SizeType ArrayNum;
|
||||||
@@ -33,14 +24,46 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
#if TARRAY_RANGED_FOR_CHECKS
|
||||||
|
typedef TCheckedPointerIterator< ElementType, SizeType> RangedForIteratorType;
|
||||||
|
typedef TCheckedPointerIterator<const ElementType, SizeType> RangedForConstIteratorType;
|
||||||
|
#else
|
||||||
|
typedef ElementType* RangedForIteratorType;
|
||||||
|
typedef const ElementType* RangedForConstIteratorType;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TARRAY_RANGED_FOR_CHECKS
|
||||||
|
FORCEINLINE friend RangedForIteratorType begin(TArray& Array) { return RangedForIteratorType(Array.ArrayNum, Array.GetData()); }
|
||||||
|
FORCEINLINE friend RangedForConstIteratorType begin(const TArray& Array) { return RangedForConstIteratorType(Array.ArrayNum, Array.GetData()); }
|
||||||
|
FORCEINLINE friend RangedForIteratorType end(TArray& Array) { return RangedForIteratorType(Array.ArrayNum, Array.GetData() + Array.Num()); }
|
||||||
|
FORCEINLINE friend RangedForConstIteratorType end(const TArray& Array) { return RangedForConstIteratorType(Array.ArrayNum, Array.GetData() + Array.Num()); }
|
||||||
|
#else
|
||||||
|
FORCEINLINE friend RangedForIteratorType begin(TArray& Array) { return Array.GetData(); }
|
||||||
|
FORCEINLINE friend RangedForConstIteratorType begin(const TArray& Array) { return Array.GetData(); }
|
||||||
|
FORCEINLINE friend RangedForIteratorType end(TArray& Array) { return Array.GetData() + Array.Num(); }
|
||||||
|
FORCEINLINE friend RangedForConstIteratorType end(const TArray& Array) { return Array.GetData() + Array.Num(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
inline InElementType& At(int i, size_t Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
inline InElementType& At(int i, size_t Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
||||||
inline InElementType& at(int i, size_t Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
inline InElementType& at(int i, size_t Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
||||||
inline InElementType* AtPtr(int i, size_t Size = sizeof(InElementType)) const { return (InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
inline InElementType* AtPtr(int i, size_t Size = sizeof(InElementType)) const { return (InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
||||||
|
|
||||||
bool IsValidIndex(int i) { return i > 0 && i < ArrayNum; }
|
bool IsValidIndex(int i) { return i > 0 && i < ArrayNum; }
|
||||||
|
|
||||||
ElementAllocatorType& GetData() const { return Data; }
|
InElementType* GetData()
|
||||||
ElementAllocatorType& GetData() { return Data; }
|
{
|
||||||
|
return (InElementType*)Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for returning a typed pointer to the first array entry.
|
||||||
|
*
|
||||||
|
* @returns Pointer to first array entry or nullptr if ArrayMax == 0.
|
||||||
|
*/
|
||||||
|
const InElementType* GetData() const
|
||||||
|
{
|
||||||
|
return (const InElementType*)Data;
|
||||||
|
}
|
||||||
|
|
||||||
void Reserve(int Number, size_t Size = sizeof(InElementType))
|
void Reserve(int Number, size_t Size = sizeof(InElementType))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,237 +1,202 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ContainerAllocationPolicies.h"
|
#include "ContainerAllocationPolicies.h"
|
||||||
|
#include "UnrealMathUtility.h"
|
||||||
static FORCEINLINE uint32 CountLeadingZeros(uint32 Value)
|
|
||||||
{
|
|
||||||
unsigned long Log2;
|
|
||||||
if (_BitScanReverse(&Log2, Value) != 0)
|
|
||||||
{
|
|
||||||
return 31 - Log2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define NumBitsPerDWORD ((int32)32)
|
#define NumBitsPerDWORD ((int32)32)
|
||||||
#define NumBitsPerDWORDLogTwo ((int32)5)
|
#define NumBitsPerDWORDLogTwo ((int32)5)
|
||||||
|
|
||||||
|
template<typename Allocator = FDefaultBitArrayAllocator>
|
||||||
|
class TBitArray;
|
||||||
|
|
||||||
|
template<typename Allocator = FDefaultBitArrayAllocator>
|
||||||
|
class TConstSetBitIterator;
|
||||||
|
|
||||||
|
template<typename Allocator /*= FDefaultBitArrayAllocator*/>
|
||||||
class TBitArray
|
class TBitArray
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TInlineAllocator<4>::ForElementType<unsigned int> Data;
|
/**
|
||||||
int NumBits;
|
* Move constructor.
|
||||||
int MaxBits;
|
*/
|
||||||
|
FORCEINLINE TBitArray(TBitArray&& Other)
|
||||||
struct FRelativeBitReference
|
|
||||||
{
|
{
|
||||||
public:
|
MoveOrCopy(*this, Other);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 Num() const { return NumBits; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor.
|
||||||
|
*/
|
||||||
|
FORCEINLINE TBitArray(const TBitArray& Copy)
|
||||||
|
: NumBits(0)
|
||||||
|
, MaxBits(0)
|
||||||
|
{
|
||||||
|
*this = Copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE const uint32* GetData() const
|
||||||
|
{
|
||||||
|
return (uint32*)AllocatorInstance.GetAllocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE uint32* GetData()
|
||||||
|
{
|
||||||
|
return (uint32*)AllocatorInstance.GetAllocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move assignment.
|
||||||
|
*/
|
||||||
|
FORCEINLINE TBitArray& operator=(TBitArray&& Other)
|
||||||
|
{
|
||||||
|
if (this != &Other)
|
||||||
|
{
|
||||||
|
MoveOrCopy(*this, Other);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef typename Allocator::template ForElementType<uint32> AllocatorType;
|
||||||
|
|
||||||
|
AllocatorType AllocatorInstance;
|
||||||
|
int32 NumBits;
|
||||||
|
int32 MaxBits;
|
||||||
|
|
||||||
|
template <typename BitArrayType>
|
||||||
|
static FORCEINLINE typename TEnableIf<TContainerTraits<BitArrayType>::MoveWillEmptyContainer>::Type MoveOrCopy(BitArrayType& ToArray, BitArrayType& FromArray)
|
||||||
|
{
|
||||||
|
ToArray.AllocatorInstance.MoveToEmpty(FromArray.AllocatorInstance);
|
||||||
|
|
||||||
|
ToArray.NumBits = FromArray.NumBits;
|
||||||
|
ToArray.MaxBits = FromArray.MaxBits;
|
||||||
|
FromArray.NumBits = 0;
|
||||||
|
FromArray.MaxBits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BitArrayType>
|
||||||
|
static FORCEINLINE typename TEnableIf<!TContainerTraits<BitArrayType>::MoveWillEmptyContainer>::Type MoveOrCopy(BitArrayType& ToArray, BitArrayType& FromArray)
|
||||||
|
{
|
||||||
|
ToArray = FromArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCENOINLINE void Realloc(int32 PreviousNumBits)
|
||||||
|
{
|
||||||
|
const int32 PreviousNumDWORDs = FMath::DivideAndRoundUp(PreviousNumBits, NumBitsPerDWORD);
|
||||||
|
const int32 MaxDWORDs = FMath::DivideAndRoundUp(MaxBits, NumBitsPerDWORD);
|
||||||
|
|
||||||
|
AllocatorInstance.ResizeAllocation(PreviousNumDWORDs, MaxDWORDs, sizeof(uint32));
|
||||||
|
|
||||||
|
if (MaxDWORDs)
|
||||||
|
{
|
||||||
|
// Reset the newly allocated slack DWORDs.
|
||||||
|
FMemory::Memzero((uint32*)AllocatorInstance.GetAllocation() + PreviousNumDWORDs, (MaxDWORDs - PreviousNumDWORDs) * sizeof(uint32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
class FRelativeBitReference
|
||||||
|
{
|
||||||
|
public:
|
||||||
FORCEINLINE explicit FRelativeBitReference(int32 BitIndex)
|
FORCEINLINE explicit FRelativeBitReference(int32 BitIndex)
|
||||||
: DWORDIndex(BitIndex >> NumBitsPerDWORDLogTwo)
|
: DWORDIndex(BitIndex >> NumBitsPerDWORDLogTwo)
|
||||||
, Mask(1 << (BitIndex & (NumBitsPerDWORD -1)))
|
, Mask(1 << (BitIndex & (NumBitsPerDWORD - 1)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 DWORDIndex;
|
int32 DWORDIndex;
|
||||||
uint32 Mask;
|
uint32 Mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Allocator>
|
||||||
|
class TConstSetBitIterator : public FRelativeBitReference
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
struct FBitReference
|
|
||||||
{
|
|
||||||
FORCEINLINE FBitReference(uint32& InData, uint32 InMask)
|
|
||||||
: Data(InData)
|
|
||||||
, Mask(InMask)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
FORCEINLINE const FBitReference(const uint32& InData, const uint32 InMask)
|
|
||||||
: Data(const_cast<uint32&>(InData))
|
|
||||||
, Mask(InMask)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE void SetBit(const bool Value)
|
/** Constructor. */
|
||||||
{
|
TConstSetBitIterator(const TBitArray<Allocator>& InArray, int32 StartIndex = 0)
|
||||||
Value ? Data |= Mask : Data &= ~Mask;
|
|
||||||
|
|
||||||
// 10011101 - Data // 10011101 - Data
|
|
||||||
// 00000010 - Mask - true | // 00000010 - Mask - false
|
|
||||||
// 10011111 - |= // 11111101 - ~
|
|
||||||
// // 10011111 - &=
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE operator bool() const
|
|
||||||
{
|
|
||||||
return (Data & Mask) != 0;
|
|
||||||
}
|
|
||||||
FORCEINLINE void operator=(const bool Value)
|
|
||||||
{
|
|
||||||
this->SetBit(Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32& Data;
|
|
||||||
uint32 Mask;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
class FBitIterator : public FRelativeBitReference
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
int32 Index;
|
|
||||||
const TBitArray& IteratedArray;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FORCEINLINE const FBitIterator(const TBitArray& ToIterate, const int32 StartIndex) // Begin
|
|
||||||
: IteratedArray(ToIterate)
|
|
||||||
, Index(StartIndex)
|
|
||||||
, FRelativeBitReference(StartIndex)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
FORCEINLINE const FBitIterator(const TBitArray& ToIterate) // End
|
|
||||||
: IteratedArray(ToIterate)
|
|
||||||
, Index(ToIterate.NumBits)
|
|
||||||
, FRelativeBitReference(ToIterate.NumBits)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE explicit operator bool() const
|
|
||||||
{
|
|
||||||
return Index < IteratedArray.Num();
|
|
||||||
}
|
|
||||||
FORCEINLINE FBitIterator& operator++()
|
|
||||||
{
|
|
||||||
++Index;
|
|
||||||
this->Mask <<= 1;
|
|
||||||
if (!this->Mask)
|
|
||||||
{
|
|
||||||
this->Mask = 1;
|
|
||||||
++this->DWORDIndex;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
FORCEINLINE bool operator*() const
|
|
||||||
{
|
|
||||||
// Thesis: Once there are more elements in the BitArray than InlineData can hold it'll just allocate all of
|
|
||||||
// them through SecondaryElements, leaving InlineData all true
|
|
||||||
|
|
||||||
if (IteratedArray.NumBits < IteratedArray.Data.NumInlineBits())
|
|
||||||
{
|
|
||||||
return (bool)FBitReference(IteratedArray.Data.GetInlineElement(this->DWORDIndex), this->Mask);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (bool)FBitReference(IteratedArray.Data.GetSecondaryElement(this->DWORDIndex), this->Mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FORCEINLINE bool operator==(const FBitIterator& OtherIt) const
|
|
||||||
{
|
|
||||||
return Index == OtherIt.Index;
|
|
||||||
}
|
|
||||||
FORCEINLINE bool operator!=(const FBitIterator& OtherIt) const
|
|
||||||
{
|
|
||||||
return Index </*=*/ OtherIt.Index;
|
|
||||||
}
|
|
||||||
FORCEINLINE bool operator < (const int32 Other) const
|
|
||||||
{
|
|
||||||
return Index < Other;
|
|
||||||
}
|
|
||||||
FORCEINLINE bool operator > (const int32 Other) const
|
|
||||||
{
|
|
||||||
return Index < Other;
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE int32 GetIndex() const
|
|
||||||
{
|
|
||||||
return Index;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class FSetBitIterator : public FRelativeBitReference
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
const TBitArray& IteratedArray;
|
|
||||||
|
|
||||||
uint32 UnvisitedBitMask;
|
|
||||||
int32 CurrentBitIndex;
|
|
||||||
int32 BaseBitIndex;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FORCEINLINE FSetBitIterator(const TBitArray& ToIterate, int32 StartIndex)
|
|
||||||
: FRelativeBitReference(StartIndex)
|
: FRelativeBitReference(StartIndex)
|
||||||
, IteratedArray(const_cast<TBitArray&>(ToIterate))
|
, Array(InArray)
|
||||||
, UnvisitedBitMask((~0U) << (StartIndex & (NumBitsPerDWORD - 1)))
|
, UnvisitedBitMask((~0U) << (StartIndex & (NumBitsPerDWORD - 1)))
|
||||||
, CurrentBitIndex(StartIndex)
|
, CurrentBitIndex(StartIndex)
|
||||||
, BaseBitIndex(StartIndex & ~(NumBitsPerDWORD - 1))
|
, BaseBitIndex(StartIndex & ~(NumBitsPerDWORD - 1))
|
||||||
{
|
{
|
||||||
if (StartIndex != IteratedArray.NumBits)
|
// check(StartIndex >= 0 && StartIndex <= Array.Num());
|
||||||
|
if (StartIndex != Array.Num())
|
||||||
{
|
{
|
||||||
FindNextSetBit();
|
FindFirstSetBit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FORCEINLINE FSetBitIterator(const TBitArray& ToIterate)
|
|
||||||
: FRelativeBitReference(ToIterate.NumBits)
|
|
||||||
, IteratedArray(const_cast<TBitArray&>(ToIterate))
|
|
||||||
, UnvisitedBitMask(0)
|
|
||||||
, CurrentBitIndex(ToIterate.NumBits)
|
|
||||||
, BaseBitIndex(ToIterate.NumBits)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE FSetBitIterator& operator++()
|
/** Forwards iteration operator. */
|
||||||
|
FORCEINLINE TConstSetBitIterator& operator++()
|
||||||
{
|
{
|
||||||
|
// Mark the current bit as visited.
|
||||||
UnvisitedBitMask &= ~this->Mask;
|
UnvisitedBitMask &= ~this->Mask;
|
||||||
|
|
||||||
FindNextSetBit();
|
// Find the first set bit that hasn't been visited yet.
|
||||||
|
FindFirstSetBit();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FORCEINLINE bool operator*() const
|
|
||||||
|
FORCEINLINE friend bool operator==(const TConstSetBitIterator& Lhs, const TConstSetBitIterator& Rhs)
|
||||||
{
|
{
|
||||||
return true;
|
// We only need to compare the bit index and the array... all the rest of the state is unobservable.
|
||||||
|
return Lhs.CurrentBitIndex == Rhs.CurrentBitIndex && &Lhs.Array == &Rhs.Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE bool operator==(const FSetBitIterator& Other) const
|
FORCEINLINE friend bool operator!=(const TConstSetBitIterator& Lhs, const TConstSetBitIterator& Rhs)
|
||||||
{
|
{
|
||||||
return CurrentBitIndex == Other.CurrentBitIndex;
|
return !(Lhs == Rhs);
|
||||||
}
|
|
||||||
FORCEINLINE bool operator!=(const FSetBitIterator& Other) const
|
|
||||||
{
|
|
||||||
return CurrentBitIndex </*=*/ Other.CurrentBitIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** conversion to "bool" returning true if the iterator is valid. */
|
||||||
FORCEINLINE explicit operator bool() const
|
FORCEINLINE explicit operator bool() const
|
||||||
{
|
{
|
||||||
return CurrentBitIndex < IteratedArray.NumBits;
|
return CurrentBitIndex < Array.Num();
|
||||||
|
}
|
||||||
|
/** inverse of the "bool" operator */
|
||||||
|
FORCEINLINE bool operator !() const
|
||||||
|
{
|
||||||
|
return !(bool)*this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Index accessor. */
|
||||||
FORCEINLINE int32 GetIndex() const
|
FORCEINLINE int32 GetIndex() const
|
||||||
{
|
{
|
||||||
return CurrentBitIndex;
|
return CurrentBitIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void FindNextSetBit()
|
const TBitArray<Allocator>& Array;
|
||||||
|
|
||||||
|
uint32 UnvisitedBitMask;
|
||||||
|
int32 CurrentBitIndex;
|
||||||
|
int32 BaseBitIndex;
|
||||||
|
|
||||||
|
|
||||||
|
/** Find the first set bit starting with the current bit, inclusive. */
|
||||||
|
void FindFirstSetBit()
|
||||||
{
|
{
|
||||||
//InlineData is the first 16-bytes of TBitArray
|
const uint32* ArrayData = Array.GetData();
|
||||||
const uint32* ArrayData = (IteratedArray.Data.SecondaryData ? IteratedArray.Data.SecondaryData : (uint32*)&IteratedArray.Data.InlineData);
|
const int32 ArrayNum = Array.Num();
|
||||||
|
|
||||||
if (!ArrayData)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const int32 ArrayNum = IteratedArray.NumBits;
|
|
||||||
const int32 LastDWORDIndex = (ArrayNum - 1) / NumBitsPerDWORD;
|
const int32 LastDWORDIndex = (ArrayNum - 1) / NumBitsPerDWORD;
|
||||||
|
|
||||||
|
// Advance to the next non-zero uint32.
|
||||||
uint32 RemainingBitMask = ArrayData[this->DWORDIndex] & UnvisitedBitMask;
|
uint32 RemainingBitMask = ArrayData[this->DWORDIndex] & UnvisitedBitMask;
|
||||||
|
|
||||||
while (!RemainingBitMask)
|
while (!RemainingBitMask)
|
||||||
{
|
{
|
||||||
++this->DWORDIndex;
|
++this->DWORDIndex;
|
||||||
BaseBitIndex += NumBitsPerDWORD;
|
BaseBitIndex += NumBitsPerDWORD;
|
||||||
|
|
||||||
if (this->DWORDIndex > LastDWORDIndex)
|
if (this->DWORDIndex > LastDWORDIndex)
|
||||||
{
|
{
|
||||||
|
// We've advanced past the end of the array.
|
||||||
CurrentBitIndex = ArrayNum;
|
CurrentBitIndex = ArrayNum;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -240,90 +205,21 @@ public:
|
|||||||
UnvisitedBitMask = ~0;
|
UnvisitedBitMask = ~0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This operation has the effect of unsetting the lowest set bit of BitMask
|
||||||
const uint32 NewRemainingBitMask = RemainingBitMask & (RemainingBitMask - 1);
|
const uint32 NewRemainingBitMask = RemainingBitMask & (RemainingBitMask - 1);
|
||||||
|
|
||||||
|
// This operation XORs the above mask with the original mask, which has the effect
|
||||||
|
// of returning only the bits which differ; specifically, the lowest bit
|
||||||
this->Mask = NewRemainingBitMask ^ RemainingBitMask;
|
this->Mask = NewRemainingBitMask ^ RemainingBitMask;
|
||||||
|
|
||||||
CurrentBitIndex = BaseBitIndex + NumBitsPerDWORD - 1 - CountLeadingZeros(this->Mask);
|
// If the Nth bit was the lowest set bit of BitMask, then this gives us N
|
||||||
|
CurrentBitIndex = BaseBitIndex + NumBitsPerDWORD - 1 - FMath::CountLeadingZeros(this->Mask);
|
||||||
|
|
||||||
|
// If we've accidentally iterated off the end of an array but still within the same DWORD
|
||||||
|
// then set the index to the last index of the array
|
||||||
if (CurrentBitIndex > ArrayNum)
|
if (CurrentBitIndex > ArrayNum)
|
||||||
{
|
{
|
||||||
CurrentBitIndex = ArrayNum;
|
CurrentBitIndex = ArrayNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
FORCEINLINE FBitIterator Iterator(int32 StartIndex)
|
|
||||||
{
|
|
||||||
return FBitIterator(*this, StartIndex);
|
|
||||||
}
|
|
||||||
FORCEINLINE FSetBitIterator SetBitIterator(int32 StartIndex)
|
|
||||||
{
|
|
||||||
return FSetBitIterator(*this, StartIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE FBitIterator begin()
|
|
||||||
{
|
|
||||||
return FBitIterator(*this, 0);
|
|
||||||
}
|
|
||||||
FORCEINLINE const FBitIterator begin() const
|
|
||||||
{
|
|
||||||
return FBitIterator(*this, 0);
|
|
||||||
}
|
|
||||||
FORCEINLINE FBitIterator end()
|
|
||||||
{
|
|
||||||
return FBitIterator(*this);
|
|
||||||
}
|
|
||||||
FORCEINLINE const FBitIterator end() const
|
|
||||||
{
|
|
||||||
return FBitIterator(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE FSetBitIterator SetBitsItBegin()
|
|
||||||
{
|
|
||||||
return FSetBitIterator(*this, 0);
|
|
||||||
}
|
|
||||||
FORCEINLINE const FSetBitIterator SetBitsItBegin() const
|
|
||||||
{
|
|
||||||
return FSetBitIterator(*this, 0);
|
|
||||||
}
|
|
||||||
FORCEINLINE const FSetBitIterator SetBitsItEnd()
|
|
||||||
{
|
|
||||||
return FSetBitIterator(*this);
|
|
||||||
}
|
|
||||||
FORCEINLINE const FSetBitIterator SetBitsItEnd() const
|
|
||||||
{
|
|
||||||
return FSetBitIterator(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
FORCEINLINE int32 Num() const
|
|
||||||
{
|
|
||||||
return NumBits;
|
|
||||||
}
|
|
||||||
FORCEINLINE int32 Max() const
|
|
||||||
{
|
|
||||||
return MaxBits;
|
|
||||||
}
|
|
||||||
FORCEINLINE bool IsSet(int32 Index) const
|
|
||||||
{
|
|
||||||
return *FBitIterator(*this, Index);
|
|
||||||
}
|
|
||||||
FORCEINLINE void Set(const int32 Index, const bool Value, bool bIsSettingAllZero = false)
|
|
||||||
{
|
|
||||||
const int32 DWORDIndex = (Index >> ((int32)5));
|
|
||||||
const int32 Mask = (1 << (Index & (((int32)32) - 1)));
|
|
||||||
|
|
||||||
if (!bIsSettingAllZero)
|
|
||||||
NumBits = Index >= NumBits ? Index < MaxBits ? Index + 1 : NumBits : NumBits;
|
|
||||||
|
|
||||||
FBitReference(Data[DWORDIndex], Mask).SetBit(Value);
|
|
||||||
}
|
|
||||||
FORCEINLINE void ZeroAll()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < MaxBits; ++i)
|
|
||||||
{
|
|
||||||
Set(i, false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
@@ -2,10 +2,26 @@
|
|||||||
|
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
|
||||||
|
enum EChannelType
|
||||||
|
{
|
||||||
|
CHTYPE_None = 0,
|
||||||
|
CHTYPE_Control = 1,
|
||||||
|
CHTYPE_Actor = 2,
|
||||||
|
CHTYPE_File = 3,
|
||||||
|
CHTYPE_Voice = 4,
|
||||||
|
CHTYPE_MAX = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EChannelCreateFlags
|
||||||
|
{
|
||||||
|
None = (1 << 0),
|
||||||
|
OpenedLocally = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
class UChannel : public UObject
|
class UChannel : public UObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void StartBecomingDormant()
|
void StartBecomingDormant() // T(REP)
|
||||||
{
|
{
|
||||||
void (*StartBecomingDormantOriginal)(UChannel* Channel) = decltype(StartBecomingDormantOriginal)(this->VFTable[0x298 / 8]);
|
void (*StartBecomingDormantOriginal)(UChannel* Channel) = decltype(StartBecomingDormantOriginal)(this->VFTable[0x298 / 8]);
|
||||||
StartBecomingDormantOriginal(this);
|
StartBecomingDormantOriginal(this);
|
||||||
|
|||||||
9
Project Reboot 3.0/ChildConnection.h
Normal file
9
Project Reboot 3.0/ChildConnection.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "NetConnection.h"
|
||||||
|
|
||||||
|
class UChildConnection : public UNetConnection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
||||||
18
Project Reboot 3.0/ChooseClass.h
Normal file
18
Project Reboot 3.0/ChooseClass.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
template<bool Predicate, typename TrueClass, typename FalseClass>
|
||||||
|
class TChooseClass;
|
||||||
|
|
||||||
|
template<typename TrueClass, typename FalseClass>
|
||||||
|
class TChooseClass<true, TrueClass, FalseClass>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef TrueClass Result;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename TrueClass, typename FalseClass>
|
||||||
|
class TChooseClass<false, TrueClass, FalseClass>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef FalseClass Result;
|
||||||
|
};
|
||||||
@@ -68,8 +68,8 @@ public:
|
|||||||
for (int i = 0; i < Names->Num(); ++i)
|
for (int i = 0; i < Names->Num(); ++i)
|
||||||
{
|
{
|
||||||
auto& Pair = Names->At(i);
|
auto& Pair = Names->At(i);
|
||||||
auto& Name = Pair.Key();
|
auto& Name = Pair.Key;
|
||||||
auto Value = Pair.Value();
|
auto Value = Pair.Value;
|
||||||
|
|
||||||
if (Name.ComparisonIndex.Value)
|
if (Name.ComparisonIndex.Value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,95 +1,48 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "NumericLimits.h"
|
#include "NumericLimits.h"
|
||||||
|
#include "UnrealTemplate.h"
|
||||||
|
#include "TypeCompatibleBytes.h"
|
||||||
|
|
||||||
template <int NumElements>
|
struct FMemory // so real place
|
||||||
class TInlineAllocator
|
|
||||||
{
|
{
|
||||||
private:
|
static inline void* (*Realloc)(void* Original, SIZE_T Count, uint32_t Alignment /* = DEFAULT_ALIGNMENT */);
|
||||||
template <int Size, int Alignment>
|
|
||||||
struct alignas(Alignment) TAlignedBytes
|
static void Free(void* Data)
|
||||||
{
|
{
|
||||||
unsigned char Pad[Size];
|
// We could use actual free..
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ElementType>
|
Realloc(Data, 0, 0);
|
||||||
struct TTypeCompatibleBytes : public TAlignedBytes<sizeof(ElementType), alignof(ElementType)>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
template <typename ElementType>
|
|
||||||
class ForElementType
|
|
||||||
{
|
|
||||||
friend class TBitArray;
|
|
||||||
|
|
||||||
private:
|
|
||||||
TTypeCompatibleBytes<ElementType> InlineData[NumElements];
|
|
||||||
|
|
||||||
ElementType* SecondaryData;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
FORCEINLINE int32 NumInlineBytes() const
|
|
||||||
{
|
|
||||||
return sizeof(ElementType) * NumElements;
|
|
||||||
}
|
|
||||||
FORCEINLINE int32 NumInlineBits() const
|
|
||||||
{
|
|
||||||
return NumInlineBytes() * 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE ElementType& operator[](int32 Index)
|
static size_t QuantizeSize(size_t Count, uint32 Alignment) // T(R)
|
||||||
{
|
{
|
||||||
return *(ElementType*)(&InlineData[Index]);
|
return Count;
|
||||||
}
|
|
||||||
FORCEINLINE const ElementType& operator[](int32 Index) const
|
|
||||||
{
|
|
||||||
return *(ElementType*)(&InlineData[Index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE void operator=(void* InElements)
|
static void* Memmove(void* Dest, const void* Src, SIZE_T Count)
|
||||||
{
|
{
|
||||||
SecondaryData = InElements;
|
memmove(Dest, Src, Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE ElementType& GetInlineElement(int32 Index)
|
static FORCEINLINE void* Memzero(void* Dest, SIZE_T Count)
|
||||||
{
|
{
|
||||||
return *(ElementType*)(&InlineData[Index]);
|
// return FPlatformMemory::Memzero(Dest, Count);
|
||||||
|
return RtlSecureZeroMemory(Dest, Count);
|
||||||
}
|
}
|
||||||
FORCEINLINE const ElementType& GetInlineElement(int32 Index) const
|
|
||||||
|
template< class T >
|
||||||
|
static FORCEINLINE void Memzero(T& Src)
|
||||||
{
|
{
|
||||||
return *(ElementType*)(&InlineData[Index]);
|
static_assert(!TIsPointer<T>::Value, "For pointers use the two parameters function");
|
||||||
|
Memzero(&Src, sizeof(T));
|
||||||
}
|
}
|
||||||
FORCEINLINE ElementType& GetSecondaryElement(int32 Index)
|
|
||||||
{
|
|
||||||
return SecondaryData[Index];
|
|
||||||
}
|
|
||||||
FORCEINLINE const ElementType& GetSecondaryElement(int32 Index) const
|
|
||||||
{
|
|
||||||
return SecondaryData[Index];
|
|
||||||
}
|
|
||||||
ElementType* GetInlineElements() const
|
|
||||||
{
|
|
||||||
return (ElementType*)InlineData;
|
|
||||||
}
|
|
||||||
FORCEINLINE ElementType* GetAllocation() const
|
|
||||||
{
|
|
||||||
return IfAThenAElseB<ElementType>(SecondaryData, GetInlineElements());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T = __int64>
|
||||||
FORCEINLINE /*FMEMORY_INLINE_FUNCTION_DECORATOR*/ size_t /*FMemory::*/QuantizeSize(SIZE_T Count, uint32 Alignment)
|
static T* AllocUnreal(size_t Size)
|
||||||
{
|
{
|
||||||
return Count;
|
return (T*)FMemory::Realloc(0, Size, 0);
|
||||||
/*
|
|
||||||
if (!FMEMORY_INLINE_GMalloc)
|
|
||||||
{
|
|
||||||
return Count;
|
|
||||||
}
|
|
||||||
return FMEMORY_INLINE_GMalloc->QuantizeSize(Count, Alignment); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@@ -97,21 +50,467 @@ enum
|
|||||||
DEFAULT_ALIGNMENT = 0
|
DEFAULT_ALIGNMENT = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename SizeType>
|
// 4.19
|
||||||
FORCEINLINE SizeType DefaultCalculateSlackReserve(SizeType NumElements, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment = DEFAULT_ALIGNMENT)
|
|
||||||
|
template <typename DestinationElementType, typename SourceElementType, typename SizeType>
|
||||||
|
FORCEINLINE void RelocateConstructItems(void* Dest, const SourceElementType* Source, SizeType Count)
|
||||||
{
|
{
|
||||||
SizeType Retval = NumElements;
|
FMemory::Memmove(Dest, Source, sizeof(SourceElementType) * Count);
|
||||||
|
/*
|
||||||
|
|
||||||
|
if constexpr (UE::Core::Private::MemoryOps::TCanBitwiseRelocate<DestinationElementType, SourceElementType>::Value)
|
||||||
|
{
|
||||||
|
FMemory::Memmove(Dest, Source, sizeof(SourceElementType) * Count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (Count)
|
||||||
|
{
|
||||||
|
// We need a typedef here because VC won't compile the destructor call below if SourceElementType itself has a member called SourceElementType
|
||||||
|
typedef SourceElementType RelocateConstructItemsElementTypeTypedef;
|
||||||
|
|
||||||
|
new (Dest) DestinationElementType(*Source);
|
||||||
|
++(DestinationElementType*&)Dest;
|
||||||
|
(Source++)->RelocateConstructItemsElementTypeTypedef::~RelocateConstructItemsElementTypeTypedef();
|
||||||
|
--Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
class FDefaultAllocator;
|
||||||
|
|
||||||
|
template <uint32 NumInlineElements, typename SecondaryAllocator = FDefaultAllocator>
|
||||||
|
class TInlineAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum { NeedsElementType = true };
|
||||||
|
enum { RequireRangeCheck = true };
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
class ForElementType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ForElementType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE void MoveToEmpty(ForElementType& Other)
|
||||||
|
{
|
||||||
|
// checkSlow(this != &Other);
|
||||||
|
|
||||||
|
if (!Other.SecondaryData.GetAllocation())
|
||||||
|
{
|
||||||
|
RelocateConstructItems<ElementType>((void*)InlineData, Other.GetInlineElements(), NumInlineElements);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move secondary storage in any case.
|
||||||
|
// This will move secondary storage if it exists but will also handle the case where secondary storage is used in Other but not in *this.
|
||||||
|
SecondaryData.MoveToEmpty(Other.SecondaryData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FContainerAllocatorInterface
|
||||||
|
FORCEINLINE ElementType* GetAllocation() const
|
||||||
|
{
|
||||||
|
return IfAThenAElseB<ElementType>(SecondaryData.GetAllocation(), GetInlineElements());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResizeAllocation(int32 PreviousNumElements, int32 NumElements, SIZE_T NumBytesPerElement)
|
||||||
|
{
|
||||||
|
// Check if the new allocation will fit in the inline data area.
|
||||||
|
if (NumElements <= NumInlineElements)
|
||||||
|
{
|
||||||
|
// If the old allocation wasn't in the inline data area, relocate it into the inline data area.
|
||||||
|
if (SecondaryData.GetAllocation())
|
||||||
|
{
|
||||||
|
RelocateConstructItems<ElementType>((void*)InlineData, (ElementType*)SecondaryData.GetAllocation(), PreviousNumElements);
|
||||||
|
|
||||||
|
// Free the old indirect allocation.
|
||||||
|
SecondaryData.ResizeAllocation(0, 0, NumBytesPerElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!SecondaryData.GetAllocation())
|
||||||
|
{
|
||||||
|
// Allocate new indirect memory for the data.
|
||||||
|
SecondaryData.ResizeAllocation(0, NumElements, NumBytesPerElement);
|
||||||
|
|
||||||
|
// Move the data out of the inline data area into the new allocation.
|
||||||
|
RelocateConstructItems<ElementType>((void*)SecondaryData.GetAllocation(), GetInlineElements(), PreviousNumElements);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Reallocate the indirect data for the new size.
|
||||||
|
SecondaryData.ResizeAllocation(PreviousNumElements, NumElements, NumBytesPerElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 CalculateSlackReserve(int32 NumElements, SIZE_T NumBytesPerElement) const
|
||||||
|
{
|
||||||
|
// If the elements use less space than the inline allocation, only use the inline allocation as slack.
|
||||||
|
return NumElements <= NumInlineElements ?
|
||||||
|
NumInlineElements :
|
||||||
|
SecondaryData.CalculateSlackReserve(NumElements, NumBytesPerElement);
|
||||||
|
}
|
||||||
|
FORCEINLINE int32 CalculateSlackShrink(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement) const
|
||||||
|
{
|
||||||
|
// If the elements use less space than the inline allocation, only use the inline allocation as slack.
|
||||||
|
return NumElements <= NumInlineElements ?
|
||||||
|
NumInlineElements :
|
||||||
|
SecondaryData.CalculateSlackShrink(NumElements, NumAllocatedElements, NumBytesPerElement);
|
||||||
|
}
|
||||||
|
FORCEINLINE int32 CalculateSlackGrow(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement) const
|
||||||
|
{
|
||||||
|
// If the elements use less space than the inline allocation, only use the inline allocation as slack.
|
||||||
|
return NumElements <= NumInlineElements ?
|
||||||
|
NumInlineElements :
|
||||||
|
SecondaryData.CalculateSlackGrow(NumElements, NumAllocatedElements, NumBytesPerElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
SIZE_T GetAllocatedSize(int32 NumAllocatedElements, SIZE_T NumBytesPerElement) const
|
||||||
|
{
|
||||||
|
return SecondaryData.GetAllocatedSize(NumAllocatedElements, NumBytesPerElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasAllocation()
|
||||||
|
{
|
||||||
|
return SecondaryData.HasAllocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ForElementType(const ForElementType&);
|
||||||
|
ForElementType& operator=(const ForElementType&);
|
||||||
|
|
||||||
|
/** The data is stored in this array if less than NumInlineElements is needed. */
|
||||||
|
TTypeCompatibleBytes<ElementType> InlineData[NumInlineElements];
|
||||||
|
|
||||||
|
/** The data is allocated through the indirect allocation policy if more than NumInlineElements is needed. */
|
||||||
|
typename SecondaryAllocator::template ForElementType<ElementType> SecondaryData;
|
||||||
|
|
||||||
|
/** @return the base of the aligned inline element data */
|
||||||
|
ElementType* GetInlineElements() const
|
||||||
|
{
|
||||||
|
return (ElementType*)InlineData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void ForAnyElementType;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct FScriptContainerElement
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
FORCEINLINE int32 DefaultCalculateSlackShrink(int32 NumElements, int32 NumAllocatedElements, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment = DEFAULT_ALIGNMENT)
|
||||||
|
{
|
||||||
|
int32 Retval;
|
||||||
|
// checkSlow(NumElements < NumAllocatedElements);
|
||||||
|
|
||||||
|
const uint32 CurrentSlackElements = NumAllocatedElements - NumElements;
|
||||||
|
const SIZE_T CurrentSlackBytes = (NumAllocatedElements - NumElements) * BytesPerElement;
|
||||||
|
const bool bTooManySlackBytes = CurrentSlackBytes >= 16384;
|
||||||
|
const bool bTooManySlackElements = 3 * NumElements < 2 * NumAllocatedElements;
|
||||||
|
if ((bTooManySlackBytes || bTooManySlackElements) && (CurrentSlackElements > 64 || !NumElements)) // hard coded 64 :-(
|
||||||
|
{
|
||||||
|
Retval = NumElements;
|
||||||
|
if (Retval > 0)
|
||||||
|
{
|
||||||
|
if (bAllowQuantize)
|
||||||
|
{
|
||||||
|
Retval = FMemory::QuantizeSize(Retval * BytesPerElement, Alignment) / BytesPerElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Retval = NumAllocatedElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 DefaultCalculateSlackGrow(int32 NumElements, int32 NumAllocatedElements, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment = DEFAULT_ALIGNMENT)
|
||||||
|
{
|
||||||
|
int32 Retval;
|
||||||
|
// checkSlow(NumElements > NumAllocatedElements && NumElements > 0);
|
||||||
|
|
||||||
|
SIZE_T Grow = 4;
|
||||||
|
if (NumAllocatedElements || SIZE_T(NumElements) > Grow)
|
||||||
|
{
|
||||||
|
// Allocate slack for the array proportional to its size.
|
||||||
|
Grow = SIZE_T(NumElements) + 3 * SIZE_T(NumElements) / 8 + 16;
|
||||||
|
}
|
||||||
|
if (bAllowQuantize)
|
||||||
|
{
|
||||||
|
Retval = FMemory::QuantizeSize(Grow * BytesPerElement, Alignment) / BytesPerElement;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Retval = Grow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumElements > Retval)
|
||||||
|
{
|
||||||
|
Retval = MAX_int32;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 DefaultCalculateSlackReserve(int32 NumElements, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment = DEFAULT_ALIGNMENT)
|
||||||
|
{
|
||||||
|
int32 Retval = NumElements;
|
||||||
// checkSlow(NumElements > 0);
|
// checkSlow(NumElements > 0);
|
||||||
if (bAllowQuantize)
|
if (bAllowQuantize)
|
||||||
{
|
{
|
||||||
auto Count = SIZE_T(Retval) * SIZE_T(BytesPerElement);
|
Retval = FMemory::QuantizeSize(SIZE_T(Retval) * SIZE_T(BytesPerElement), Alignment) / BytesPerElement;
|
||||||
Retval = (SizeType)(QuantizeSize(Count, Alignment) / BytesPerElement);
|
|
||||||
// NumElements and MaxElements are stored in 32 bit signed integers so we must be careful not to overflow here.
|
// NumElements and MaxElements are stored in 32 bit signed integers so we must be careful not to overflow here.
|
||||||
if (NumElements > Retval)
|
if (NumElements > Retval)
|
||||||
{
|
{
|
||||||
Retval = TNumericLimits<SizeType>::Max();
|
Retval = MAX_int32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Retval;
|
return Retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FHeapAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum { NeedsElementType = false };
|
||||||
|
enum { RequireRangeCheck = true };
|
||||||
|
|
||||||
|
class ForAnyElementType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Default constructor. */
|
||||||
|
ForAnyElementType()
|
||||||
|
: Data(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
|
FORCEINLINE void MoveToEmpty(ForAnyElementType& Other)
|
||||||
|
{
|
||||||
|
// checkSlow(this != &Other);
|
||||||
|
|
||||||
|
if (Data)
|
||||||
|
{
|
||||||
|
FMemory::Free(Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Data = Other.Data;
|
||||||
|
Other.Data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Destructor. */
|
||||||
|
FORCEINLINE ~ForAnyElementType()
|
||||||
|
{
|
||||||
|
if (Data)
|
||||||
|
{
|
||||||
|
FMemory::Free(Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FContainerAllocatorInterface
|
||||||
|
FORCEINLINE FScriptContainerElement* GetAllocation() const
|
||||||
|
{
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
FORCEINLINE void ResizeAllocation(int32 PreviousNumElements, int32 NumElements, SIZE_T NumBytesPerElement)
|
||||||
|
{
|
||||||
|
// Avoid calling FMemory::Realloc( nullptr, 0 ) as ANSI C mandates returning a valid pointer which is not what we want.
|
||||||
|
if (Data || NumElements)
|
||||||
|
{
|
||||||
|
//checkSlow(((uint64)NumElements*(uint64)ElementTypeInfo.GetSize() < (uint64)INT_MAX));
|
||||||
|
Data = (FScriptContainerElement*)FMemory::Realloc(Data, NumElements * NumBytesPerElement, DEFAULT_ALIGNMENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FORCEINLINE int32 CalculateSlackReserve(int32 NumElements, int32 NumBytesPerElement) const
|
||||||
|
{
|
||||||
|
return DefaultCalculateSlackReserve(NumElements, NumBytesPerElement, true);
|
||||||
|
}
|
||||||
|
FORCEINLINE int32 CalculateSlackShrink(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement) const
|
||||||
|
{
|
||||||
|
return DefaultCalculateSlackShrink(NumElements, NumAllocatedElements, NumBytesPerElement, true);
|
||||||
|
}
|
||||||
|
FORCEINLINE int32 CalculateSlackGrow(int32 NumElements, int32 NumAllocatedElements, int32 NumBytesPerElement) const
|
||||||
|
{
|
||||||
|
return DefaultCalculateSlackGrow(NumElements, NumAllocatedElements, NumBytesPerElement, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SIZE_T GetAllocatedSize(int32 NumAllocatedElements, SIZE_T NumBytesPerElement) const
|
||||||
|
{
|
||||||
|
return NumAllocatedElements * NumBytesPerElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HasAllocation()
|
||||||
|
{
|
||||||
|
return !!Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ForAnyElementType(const ForAnyElementType&);
|
||||||
|
ForAnyElementType& operator=(const ForAnyElementType&);
|
||||||
|
|
||||||
|
/** A pointer to the container's elements. */
|
||||||
|
FScriptContainerElement* Data;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ElementType>
|
||||||
|
class ForElementType : public ForAnyElementType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Default constructor. */
|
||||||
|
ForElementType()
|
||||||
|
{}
|
||||||
|
|
||||||
|
FORCEINLINE ElementType* GetAllocation() const
|
||||||
|
{
|
||||||
|
return (ElementType*)ForAnyElementType::GetAllocation();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FDefaultAllocator;
|
||||||
|
class FDefaultBitArrayAllocator;
|
||||||
|
|
||||||
|
/** Encapsulates the allocators used by a sparse array in a single type. */
|
||||||
|
template<typename InElementAllocator = FDefaultAllocator, typename InBitArrayAllocator = FDefaultBitArrayAllocator>
|
||||||
|
class TSparseArrayAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef InElementAllocator ElementAllocator;
|
||||||
|
typedef InBitArrayAllocator BitArrayAllocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** An inline sparse array allocator that allows sizing of the inline allocations for a set number of elements. */
|
||||||
|
template<
|
||||||
|
uint32 NumInlineElements,
|
||||||
|
typename SecondaryAllocator = TSparseArrayAllocator<FDefaultAllocator, FDefaultAllocator>
|
||||||
|
>
|
||||||
|
class TInlineSparseArrayAllocator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** The size to allocate inline for the bit array. */
|
||||||
|
enum { InlineBitArrayDWORDs = (NumInlineElements + NumBitsPerDWORD - 1) / NumBitsPerDWORD };
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef TInlineAllocator<NumInlineElements, typename SecondaryAllocator::ElementAllocator> ElementAllocator;
|
||||||
|
typedef TInlineAllocator<InlineBitArrayDWORDs, typename SecondaryAllocator::BitArrayAllocator> BitArrayAllocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFAULT_NUMBER_OF_ELEMENTS_PER_HASH_BUCKET 2
|
||||||
|
#define DEFAULT_BASE_NUMBER_OF_HASH_BUCKETS 8
|
||||||
|
#define DEFAULT_MIN_NUMBER_OF_HASHED_ELEMENTS 4
|
||||||
|
|
||||||
|
static FORCEINLINE uint32 CountLeadingZeros(uint32 Value)
|
||||||
|
{
|
||||||
|
unsigned long Log2;
|
||||||
|
if (_BitScanReverse(&Log2, Value) != 0)
|
||||||
|
{
|
||||||
|
return 31 - Log2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
static /* constexpr */ FORCEINLINE uint32 CeilLogTwo(uint32 Arg) // Milxnor: really in FPlatformMath
|
||||||
|
{
|
||||||
|
Arg = Arg ? Arg : 1;
|
||||||
|
return 32 - CountLeadingZeros(Arg - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static /* constexpr */ FORCEINLINE uint32 RoundUpToPowerOfTwo(uint32 Arg) // Milxnor: really in FPlatformMath
|
||||||
|
{
|
||||||
|
return 1 << CeilLogTwo(Arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename InSparseArrayAllocator = TSparseArrayAllocator<>,
|
||||||
|
typename InHashAllocator = TInlineAllocator<1, FDefaultAllocator>,
|
||||||
|
uint32 AverageNumberOfElementsPerHashBucket = DEFAULT_NUMBER_OF_ELEMENTS_PER_HASH_BUCKET,
|
||||||
|
uint32 BaseNumberOfHashBuckets = DEFAULT_BASE_NUMBER_OF_HASH_BUCKETS,
|
||||||
|
uint32 MinNumberOfHashedElements = DEFAULT_MIN_NUMBER_OF_HASHED_ELEMENTS
|
||||||
|
>
|
||||||
|
class TSetAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Computes the number of hash buckets to use for a given number of elements. */
|
||||||
|
static FORCEINLINE uint32 GetNumberOfHashBuckets(uint32 NumHashedElements)
|
||||||
|
{
|
||||||
|
if (NumHashedElements >= MinNumberOfHashedElements)
|
||||||
|
{
|
||||||
|
return RoundUpToPowerOfTwo(NumHashedElements / AverageNumberOfElementsPerHashBucket + BaseNumberOfHashBuckets);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef InSparseArrayAllocator SparseArrayAllocator;
|
||||||
|
typedef InHashAllocator HashAllocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FDefaultAllocator;
|
||||||
|
|
||||||
|
/** An inline set allocator that allows sizing of the inline allocations for a set number of elements. */
|
||||||
|
template<
|
||||||
|
uint32 NumInlineElements,
|
||||||
|
typename SecondaryAllocator = TSetAllocator<TSparseArrayAllocator<FDefaultAllocator, FDefaultAllocator>, FDefaultAllocator>,
|
||||||
|
uint32 AverageNumberOfElementsPerHashBucket = DEFAULT_NUMBER_OF_ELEMENTS_PER_HASH_BUCKET,
|
||||||
|
uint32 MinNumberOfHashedElements = DEFAULT_MIN_NUMBER_OF_HASHED_ELEMENTS
|
||||||
|
>
|
||||||
|
class TInlineSetAllocator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum { NumInlineHashBuckets = (NumInlineElements + AverageNumberOfElementsPerHashBucket - 1) / AverageNumberOfElementsPerHashBucket };
|
||||||
|
|
||||||
|
static_assert(!(NumInlineHashBuckets& (NumInlineHashBuckets - 1)), "Number of inline buckets must be a power of two");
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Computes the number of hash buckets to use for a given number of elements. */
|
||||||
|
static FORCEINLINE uint32 GetNumberOfHashBuckets(uint32 NumHashedElements)
|
||||||
|
{
|
||||||
|
const uint32 NumDesiredHashBuckets = RoundUpToPowerOfTwo(NumHashedElements / AverageNumberOfElementsPerHashBucket);
|
||||||
|
if (NumDesiredHashBuckets < NumInlineHashBuckets)
|
||||||
|
{
|
||||||
|
return NumInlineHashBuckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumHashedElements < MinNumberOfHashedElements)
|
||||||
|
{
|
||||||
|
return NumInlineHashBuckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NumDesiredHashBuckets;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef TInlineSparseArrayAllocator<NumInlineElements, typename SecondaryAllocator::SparseArrayAllocator> SparseArrayAllocator;
|
||||||
|
typedef TInlineAllocator<NumInlineHashBuckets, typename SecondaryAllocator::HashAllocator> HashAllocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 'typedefs' for various allocator defaults.
|
||||||
|
*
|
||||||
|
* These should be replaced with actual typedefs when Core.h include order is sorted out, as then we won't need to
|
||||||
|
* 'forward' these TAllocatorTraits specializations below.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class FDefaultAllocator : public FHeapAllocator { public: typedef FHeapAllocator Typedef; };
|
||||||
|
class FDefaultSetAllocator : public TSetAllocator<> { public: typedef TSetAllocator<> Typedef; };
|
||||||
|
class FDefaultBitArrayAllocator : public TInlineAllocator<4> { public: typedef TInlineAllocator<4> Typedef; };
|
||||||
|
class FDefaultSparseArrayAllocator : public TSparseArrayAllocator<> { public: typedef TSparseArrayAllocator<> Typedef; };
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ class UDataTable : public UObject
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <typename RowDataType = uint8_t>
|
template <typename RowDataType = uint8_t>
|
||||||
TMap<FName, RowDataType*>& GetRowMap()
|
TMap<FName, RowDataType>& GetRowMap()
|
||||||
{
|
{
|
||||||
static auto RowStructOffset = FindOffsetStruct("/Script/Engine.DataTable", "RowStruct");
|
static auto RowStructOffset = FindOffsetStruct("/Script/Engine.DataTable", "RowStruct");
|
||||||
|
|
||||||
return *(TMap<FName, RowDataType*>*)(__int64(this) + (RowStructOffset + sizeof(UObject*))); // because after rowstruct is rowmap
|
return *(TMap<FName, RowDataType>*)(__int64(this) + (RowStructOffset + sizeof(UObject*))); // because after rowstruct is rowmap
|
||||||
}
|
}
|
||||||
|
|
||||||
static UClass* StaticClass()
|
static UClass* StaticClass()
|
||||||
|
|||||||
@@ -78,9 +78,9 @@ public:
|
|||||||
|
|
||||||
for (auto& AwardEntry : AwardEntriesAtElimMap)
|
for (auto& AwardEntry : AwardEntriesAtElimMap)
|
||||||
{
|
{
|
||||||
if (AwardEntry.First == Value)
|
if (AwardEntry.Key == Value)
|
||||||
{
|
{
|
||||||
return AwardEntry.Second;
|
return AwardEntry.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,8 +109,8 @@ FName AFortGameModeAthena::RedirectLootTier(const FName& LootTier)
|
|||||||
|
|
||||||
for (auto& Pair : RedirectAthenaLootTierGroups)
|
for (auto& Pair : RedirectAthenaLootTierGroups)
|
||||||
{
|
{
|
||||||
auto& Key = Pair.Key();
|
auto& Key = Pair.Key;
|
||||||
auto& Value = Pair.Value();
|
auto& Value = Pair.Value;
|
||||||
|
|
||||||
// LOG_INFO(LogDev, "[{}] {} {}", i, Key.ComparisonIndex.Value ? Key.ToString() : "NULL", Key.ComparisonIndex.Value ? Value.ToString() : "NULL");
|
// LOG_INFO(LogDev, "[{}] {} {}", i, Key.ComparisonIndex.Value ? Key.ToString() : "NULL", Key.ComparisonIndex.Value ? Value.ToString() : "NULL");
|
||||||
|
|
||||||
@@ -428,6 +428,7 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto OldPlaylist = GetPlaylistForOldVersion();
|
auto OldPlaylist = GetPlaylistForOldVersion();
|
||||||
|
SetupEverythingAI();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Fortnite_Season = std::floor(Fortnite_Version);
|
auto Fortnite_Season = std::floor(Fortnite_Version);
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ float UFortItemDefinition::GetMaxStackSize()
|
|||||||
|
|
||||||
for (auto& Pair : RowMap)
|
for (auto& Pair : RowMap)
|
||||||
{
|
{
|
||||||
if (Pair.Key() == ScalableFloat.Curve.RowName)
|
if (Pair.Key == ScalableFloat.Curve.RowName)
|
||||||
{
|
{
|
||||||
Curve = (FSimpleCurve*)Pair.Value();
|
Curve = (FSimpleCurve*)Pair.Value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ int UFortLootLevel::GetItemLevel(const FDataTableCategoryHandle& LootLevelData,
|
|||||||
|
|
||||||
for (auto& LootLevelDataPair : LootLevelData.DataTable->GetRowMap<FFortLootLevelData>())
|
for (auto& LootLevelDataPair : LootLevelData.DataTable->GetRowMap<FFortLootLevelData>())
|
||||||
{
|
{
|
||||||
if (LootLevelDataPair.Second->Category != LootLevelData.RowContents)
|
if (LootLevelDataPair.Value.Category != LootLevelData.RowContents)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
OurLootLevelDatas.push_back(LootLevelDataPair.Second);
|
OurLootLevelDatas.push_back(&LootLevelDataPair.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OurLootLevelDatas.size() > 0)
|
if (OurLootLevelDatas.size() > 0)
|
||||||
|
|||||||
@@ -47,14 +47,16 @@ void CollectDataTablesRows(const std::vector<UDataTable*>& DataTables, LOOTING_M
|
|||||||
DataTablesToIterate.push_back(DataTable);
|
DataTablesToIterate.push_back(DataTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return; // T(1)
|
||||||
|
|
||||||
for (auto CurrentDataTable : DataTablesToIterate)
|
for (auto CurrentDataTable : DataTablesToIterate)
|
||||||
{
|
{
|
||||||
for (TPair<FName, uint8_t*>& CurrentPair : CurrentDataTable->GetRowMap())
|
for (auto& CurrentPair : CurrentDataTable->GetRowMap())
|
||||||
{
|
{
|
||||||
if (Check(CurrentPair.Key(), (RowStructType*)CurrentPair.Value()))
|
if (Check(CurrentPair.Key, (RowStructType*)CurrentPair.Value))
|
||||||
{
|
{
|
||||||
// LOG_INFO(LogDev, "Setting key with {} comp {} num: {} then iterating through map!", CurrentPair.Key().ToString(), CurrentPair.Key().ComparisonIndex.Value, CurrentPair.Key().Number);
|
// LOG_INFO(LogDev, "Setting key with {} comp {} num: {} then iterating through map!", CurrentPair.Key().ToString(), CurrentPair.Key().ComparisonIndex.Value, CurrentPair.Key().Number);
|
||||||
(*OutMap)[CurrentPair.Key()] = (RowStructType*)CurrentPair.Value();
|
(*OutMap)[CurrentPair.Key] = (RowStructType*)CurrentPair.Value;
|
||||||
|
|
||||||
/* for (auto PairInOutMap : *OutMap)
|
/* for (auto PairInOutMap : *OutMap)
|
||||||
{
|
{
|
||||||
@@ -503,14 +505,14 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int WorldLevel, int For
|
|||||||
|
|
||||||
for (auto& Value : PlaylistOverrideLootTableData)
|
for (auto& Value : PlaylistOverrideLootTableData)
|
||||||
{
|
{
|
||||||
auto CurrentOverrideTag = Value.First;
|
auto CurrentOverrideTag = Value.Key;
|
||||||
|
|
||||||
if (Tag.TagName == CurrentOverrideTag.TagName)
|
if (Tag.TagName == CurrentOverrideTag.TagName)
|
||||||
{
|
{
|
||||||
auto OverrideLootPackageTableStr = Value.Second.LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
auto OverrideLootPackageTableStr = Value.Value.LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
auto bOverrideIsComposite = OverrideLootPackageTableStr.contains("Composite");
|
auto bOverrideIsComposite = OverrideLootPackageTableStr.contains("Composite");
|
||||||
|
|
||||||
auto ptr = Value.Second.LootPackageData.Get(bOverrideIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
auto ptr = Value.Value.LootPackageData.Get(bOverrideIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
@@ -557,14 +559,14 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int WorldLevel, int For
|
|||||||
|
|
||||||
for (auto& Value : PlaylistOverrideLootTableData)
|
for (auto& Value : PlaylistOverrideLootTableData)
|
||||||
{
|
{
|
||||||
auto CurrentOverrideTag = Value.First;
|
auto CurrentOverrideTag = Value.Key;
|
||||||
|
|
||||||
if (Tag.TagName == CurrentOverrideTag.TagName)
|
if (Tag.TagName == CurrentOverrideTag.TagName)
|
||||||
{
|
{
|
||||||
auto OverrideLootTierDataStr = Value.Second.LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
auto OverrideLootTierDataStr = Value.Value.LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
auto bOverrideIsComposite = OverrideLootTierDataStr.contains("Composite");
|
auto bOverrideIsComposite = OverrideLootTierDataStr.contains("Composite");
|
||||||
|
|
||||||
auto ptr = Value.Second.LootTierData.Get(bOverrideIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
auto ptr = Value.Value.LootTierData.Get(bOverrideIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -567,6 +567,10 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
|||||||
|
|
||||||
FWeaponUpgradeItemRow* FoundRow = nullptr;
|
FWeaponUpgradeItemRow* FoundRow = nullptr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
T(3)
|
||||||
|
|
||||||
for (int i = 0; i < LootPackagesRowMap.Pairs.Elements.Data.Num(); i++)
|
for (int i = 0; i < LootPackagesRowMap.Pairs.Elements.Data.Num(); i++)
|
||||||
{
|
{
|
||||||
auto& Pair = LootPackagesRowMap.Pairs.Elements.Data.at(i).ElementData.Value;
|
auto& Pair = LootPackagesRowMap.Pairs.Elements.Data.at(i).ElementData.Value;
|
||||||
@@ -580,6 +584,8 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
if (!FoundRow)
|
if (!FoundRow)
|
||||||
{
|
{
|
||||||
LOG_WARN(LogGame, "Failed to find row!");
|
LOG_WARN(LogGame, "Failed to find row!");
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ int UFortWeaponItemDefinition::GetClipSize()
|
|||||||
|
|
||||||
void* Row = nullptr;
|
void* Row = nullptr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
T(1)
|
||||||
|
|
||||||
for (int i = 0; i < RowMap.Pairs.Elements.Data.Num(); ++i)
|
for (int i = 0; i < RowMap.Pairs.Elements.Data.Num(); ++i)
|
||||||
{
|
{
|
||||||
auto& Pair = RowMap.Pairs.Elements.Data.at(i).ElementData.Value;
|
auto& Pair = RowMap.Pairs.Elements.Data.at(i).ElementData.Value;
|
||||||
@@ -28,6 +32,8 @@ int UFortWeaponItemDefinition::GetClipSize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
if (!Row)
|
if (!Row)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "Level.h"
|
#include "Level.h"
|
||||||
|
#include "reboot.h"
|
||||||
|
|
||||||
UWorld*& ULevel::GetOwningWorld()
|
UWorld*& ULevel::GetOwningWorld()
|
||||||
{
|
{
|
||||||
@@ -6,7 +7,7 @@ UWorld*& ULevel::GetOwningWorld()
|
|||||||
return Get<UWorld*>(OwningWorldOffset);
|
return Get<UWorld*>(OwningWorldOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ULevel::HasVisibilityChangeRequestPending()
|
bool ULevel::HasVisibilityChangeRequestPending() // T(REP)
|
||||||
{
|
{
|
||||||
// I believe implementation on this changes depending on the version
|
// I believe implementation on this changes depending on the version
|
||||||
|
|
||||||
@@ -24,6 +25,11 @@ bool ULevel::HasVisibilityChangeRequestPending()
|
|||||||
return this == CurrentLevelPendingVisibility || this == CurrentLevelPendingInvisibility;
|
return this == CurrentLevelPendingVisibility || this == CurrentLevelPendingInvisibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ULevel::IsAssociatingLevel() // T(REP)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
AWorldSettings* ULevel::GetWorldSettings(bool bChecked) const
|
AWorldSettings* ULevel::GetWorldSettings(bool bChecked) const
|
||||||
{
|
{
|
||||||
if (bChecked)
|
if (bChecked)
|
||||||
@@ -34,3 +40,9 @@ AWorldSettings* ULevel::GetWorldSettings(bool bChecked) const
|
|||||||
static auto WorldSettingsOffset = GetOffset("WorldSettings");
|
static auto WorldSettingsOffset = GetOffset("WorldSettings");
|
||||||
return Get<AWorldSettings*>(WorldSettingsOffset);
|
return Get<AWorldSettings*>(WorldSettingsOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UClass* ULevel::StaticClass()
|
||||||
|
{
|
||||||
|
static auto Class = FindObject<UClass>(L"/Script/Engine.Level");
|
||||||
|
return Class;
|
||||||
|
}
|
||||||
@@ -7,5 +7,8 @@ class ULevel : public UObject
|
|||||||
public:
|
public:
|
||||||
UWorld*& GetOwningWorld();
|
UWorld*& GetOwningWorld();
|
||||||
bool HasVisibilityChangeRequestPending();
|
bool HasVisibilityChangeRequestPending();
|
||||||
|
bool IsAssociatingLevel();
|
||||||
AWorldSettings* GetWorldSettings(bool bChecked = true) const;
|
AWorldSettings* GetWorldSettings(bool bChecked = true) const;
|
||||||
|
|
||||||
|
static class UClass* StaticClass();
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Set.h"
|
#include "Set.h"
|
||||||
|
#include "UnrealTemplate.h"
|
||||||
|
#include "ChooseClass.h"
|
||||||
|
|
||||||
// template <typename KeyType, typename ValueType>
|
// template <typename KeyType, typename ValueType>
|
||||||
// using TPair = TTuple<KeyType, ValueType>;
|
// using TPair = TTuple<KeyType, ValueType>;
|
||||||
@@ -9,151 +11,370 @@ template <typename KeyType, typename ValueType>
|
|||||||
class TPair
|
class TPair
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KeyType First;
|
KeyType Key;
|
||||||
ValueType Second;
|
ValueType Value;
|
||||||
|
};
|
||||||
|
|
||||||
FORCEINLINE KeyType& Key()
|
template <typename KeyInitType, typename ValueInitType>
|
||||||
|
class TPairInitializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typename TRValueToLValueReference<KeyInitType >::Type Key;
|
||||||
|
typename TRValueToLValueReference<ValueInitType>::Type Value;
|
||||||
|
|
||||||
|
/** Initialization constructor. */
|
||||||
|
FORCEINLINE TPairInitializer(KeyInitType InKey, ValueInitType InValue)
|
||||||
|
: Key(InKey)
|
||||||
|
, Value(InValue)
|
||||||
{
|
{
|
||||||
return First;
|
|
||||||
}
|
}
|
||||||
FORCEINLINE const KeyType& Key() const
|
|
||||||
|
/** Implicit conversion to pair initializer. */
|
||||||
|
template <typename KeyType, typename ValueType>
|
||||||
|
FORCEINLINE TPairInitializer(const TPair<KeyType, ValueType>& Pair)
|
||||||
|
: Key(Pair.Key)
|
||||||
|
, Value(Pair.Value)
|
||||||
{
|
{
|
||||||
return First;
|
|
||||||
}
|
}
|
||||||
FORCEINLINE ValueType& Value()
|
|
||||||
|
template <typename KeyType, typename ValueType>
|
||||||
|
operator TPair<KeyType, ValueType>() const
|
||||||
{
|
{
|
||||||
return Second;
|
#define StaticCast static_cast // Milxnor: ??
|
||||||
}
|
return TPair<KeyType, ValueType>(StaticCast<KeyInitType>(Key), StaticCast<ValueInitType>(Value));
|
||||||
FORCEINLINE const ValueType& Value() const
|
|
||||||
{
|
|
||||||
return Second;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename KeyType, typename ValueType>
|
template<typename KeyType, typename ValueType, bool bInAllowDuplicateKeys>
|
||||||
class TMap
|
struct TDefaultMapKeyFuncs : BaseKeyFuncs<TPair<KeyType, ValueType>, KeyType, bInAllowDuplicateKeys>
|
||||||
{
|
{
|
||||||
|
typedef typename TTypeTraits<KeyType>::ConstPointerType KeyInitType;
|
||||||
|
typedef const TPairInitializer<typename TTypeTraits<KeyType>::ConstInitType, typename TTypeTraits<ValueType>::ConstInitType>& ElementInitType;
|
||||||
|
|
||||||
|
static FORCEINLINE KeyInitType GetSetKey(ElementInitType Element)
|
||||||
|
{
|
||||||
|
return Element.Key;
|
||||||
|
}
|
||||||
|
static FORCEINLINE bool Matches(KeyInitType A, KeyInitType B)
|
||||||
|
{
|
||||||
|
return A == B;
|
||||||
|
}
|
||||||
|
static FORCEINLINE uint32 GetKeyHash(KeyInitType Key)
|
||||||
|
{
|
||||||
|
return GetTypeHash(Key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename KeyType, typename ValueType, bool bInAllowDuplicateKeys>
|
||||||
|
struct TDefaultMapHashableKeyFuncs : TDefaultMapKeyFuncs<KeyType, ValueType, bInAllowDuplicateKeys>
|
||||||
|
{
|
||||||
|
// static_assert(THasGetTypeHash<KeyType>::Value, "TMap must have a hashable KeyType unless a custom key func is provided."); // T(R)
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename KeyType, typename ValueType, typename SetAllocator, typename KeyFuncs>
|
||||||
|
class TMapBase
|
||||||
|
{
|
||||||
|
template <typename OtherKeyType, typename OtherValueType, typename OtherSetAllocator, typename OtherKeyFuncs>
|
||||||
|
friend class TMapBase;
|
||||||
|
|
||||||
|
friend struct TContainerTraits<TMapBase>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef typename TTypeTraits<KeyType >::ConstPointerType KeyConstPointerType;
|
||||||
|
typedef typename TTypeTraits<KeyType >::ConstInitType KeyInitType;
|
||||||
|
typedef typename TTypeTraits<ValueType>::ConstInitType ValueInitType;
|
||||||
typedef TPair<KeyType, ValueType> ElementType;
|
typedef TPair<KeyType, ValueType> ElementType;
|
||||||
|
|
||||||
public:
|
protected:
|
||||||
TSet<ElementType> Pairs;
|
TMapBase() = default;
|
||||||
|
TMapBase(TMapBase&&) = default;
|
||||||
|
TMapBase(const TMapBase&) = default;
|
||||||
|
TMapBase& operator=(TMapBase&&) = default;
|
||||||
|
TMapBase& operator=(const TMapBase&) = default;
|
||||||
|
|
||||||
public:
|
typedef TSet<ElementType, KeyFuncs, SetAllocator> ElementSetType;
|
||||||
class FBaseIterator
|
|
||||||
|
/** The base of TMapBase iterators. */
|
||||||
|
template<bool bConst, bool bRangedFor = false>
|
||||||
|
class TBaseIterator
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
typedef typename TChooseClass<
|
||||||
|
bConst,
|
||||||
|
typename TChooseClass<bRangedFor, typename ElementSetType::TRangedForConstIterator, typename ElementSetType::TConstIterator>::Result,
|
||||||
|
typename TChooseClass<bRangedFor, typename ElementSetType::TRangedForIterator, typename ElementSetType::TIterator >::Result
|
||||||
|
>::Result PairItType;
|
||||||
private:
|
private:
|
||||||
TMap<KeyType, ValueType>& IteratedMap;
|
typedef typename TChooseClass<bConst, const TMapBase, TMapBase>::Result MapType;
|
||||||
TSet<ElementType>::FBaseIterator SetIt;
|
typedef typename TChooseClass<bConst, const KeyType, KeyType>::Result ItKeyType;
|
||||||
|
typedef typename TChooseClass<bConst, const ValueType, ValueType>::Result ItValueType;
|
||||||
|
typedef typename TChooseClass<bConst, const typename ElementSetType::ElementType, typename ElementSetType::ElementType>::Result PairType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FBaseIterator(TMap<KeyType, ValueType>& InMap, TSet<ElementType>::FBaseIterator InSet)
|
FORCEINLINE TBaseIterator(const PairItType& InElementIt)
|
||||||
: IteratedMap(InMap)
|
: PairIt(InElementIt)
|
||||||
, SetIt(InSet)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
FORCEINLINE TMap<KeyType, ValueType>::FBaseIterator operator++()
|
|
||||||
|
FORCEINLINE TBaseIterator& operator++()
|
||||||
|
{
|
||||||
|
++PairIt;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** conversion to "bool" returning true if the iterator is valid. */
|
||||||
|
FORCEINLINE explicit operator bool() const
|
||||||
|
{
|
||||||
|
return !!PairIt;
|
||||||
|
}
|
||||||
|
/** inverse of the "bool" operator */
|
||||||
|
FORCEINLINE bool operator !() const
|
||||||
|
{
|
||||||
|
return !(bool)*this;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE friend bool operator==(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.PairIt == Rhs.PairIt; }
|
||||||
|
FORCEINLINE friend bool operator!=(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.PairIt != Rhs.PairIt; }
|
||||||
|
|
||||||
|
FORCEINLINE ItKeyType& Key() const { return PairIt->Key; }
|
||||||
|
FORCEINLINE ItValueType& Value() const { return PairIt->Value; }
|
||||||
|
|
||||||
|
FORCEINLINE PairType& operator* () const { return *PairIt; }
|
||||||
|
FORCEINLINE PairType* operator->() const { return &*PairIt; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PairItType PairIt;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The base type of iterators that iterate over the values associated with a specified key. */
|
||||||
|
template<bool bConst>
|
||||||
|
class TBaseKeyIterator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
typedef typename TChooseClass<bConst, typename ElementSetType::TConstKeyIterator, typename ElementSetType::TKeyIterator>::Result SetItType;
|
||||||
|
typedef typename TChooseClass<bConst, const KeyType, KeyType>::Result ItKeyType;
|
||||||
|
typedef typename TChooseClass<bConst, const ValueType, ValueType>::Result ItValueType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Initialization constructor. */
|
||||||
|
FORCEINLINE TBaseKeyIterator(const SetItType& InSetIt)
|
||||||
|
: SetIt(InSetIt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE TBaseKeyIterator& operator++()
|
||||||
{
|
{
|
||||||
++SetIt;
|
++SetIt;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FORCEINLINE TMap<KeyType, ValueType>::ElementType& operator*()
|
|
||||||
|
/** conversion to "bool" returning true if the iterator is valid. */
|
||||||
|
FORCEINLINE explicit operator bool() const
|
||||||
{
|
{
|
||||||
return *SetIt;
|
return !!SetIt;
|
||||||
}
|
}
|
||||||
FORCEINLINE const TMap<KeyType, ValueType>::ElementType& operator*() const
|
/** inverse of the "bool" operator */
|
||||||
|
FORCEINLINE bool operator !() const
|
||||||
{
|
{
|
||||||
return *SetIt;
|
return !(bool)*this;
|
||||||
}
|
}
|
||||||
FORCEINLINE bool operator==(const TMap<KeyType, ValueType>::FBaseIterator& Other) const
|
|
||||||
|
FORCEINLINE ItKeyType& Key() const { return SetIt->Key; }
|
||||||
|
FORCEINLINE ItValueType& Value() const { return SetIt->Value; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SetItType SetIt;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A set of the key-value pairs in the map. */
|
||||||
|
ElementSetType Pairs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Map iterator. */
|
||||||
|
class TIterator : public TBaseIterator<false>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/** Initialization constructor. */
|
||||||
|
FORCEINLINE TIterator(TMapBase& InMap, bool bInRequiresRehashOnRemoval = false)
|
||||||
|
: TBaseIterator<false>(InMap.Pairs.CreateIterator())
|
||||||
|
, Map(InMap)
|
||||||
|
, bElementsHaveBeenRemoved(false)
|
||||||
|
, bRequiresRehashOnRemoval(bInRequiresRehashOnRemoval)
|
||||||
{
|
{
|
||||||
return SetIt == Other.SetIt;
|
|
||||||
}
|
}
|
||||||
FORCEINLINE bool operator!=(const TMap<KeyType, ValueType>::FBaseIterator& Other) const
|
|
||||||
|
/** Destructor. */
|
||||||
|
FORCEINLINE ~TIterator()
|
||||||
{
|
{
|
||||||
return SetIt != Other.SetIt;
|
if (bElementsHaveBeenRemoved && bRequiresRehashOnRemoval)
|
||||||
|
{
|
||||||
|
Map.Pairs.Relax();
|
||||||
}
|
}
|
||||||
FORCEINLINE bool IsElementValid() const
|
}
|
||||||
|
|
||||||
|
/** Removes the current pair from the map. */
|
||||||
|
FORCEINLINE void RemoveCurrent()
|
||||||
|
{
|
||||||
|
TBaseIterator<false>::PairIt.RemoveCurrent();
|
||||||
|
bElementsHaveBeenRemoved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TMapBase& Map;
|
||||||
|
bool bElementsHaveBeenRemoved;
|
||||||
|
bool bRequiresRehashOnRemoval;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Const map iterator. */
|
||||||
|
class TConstIterator : public TBaseIterator<true>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FORCEINLINE TConstIterator(const TMapBase& InMap)
|
||||||
|
: TBaseIterator<true>(InMap.Pairs.CreateConstIterator())
|
||||||
{
|
{
|
||||||
return SetIt.IsElementValid();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
FORCEINLINE TMap<KeyType, ValueType>::FBaseIterator begin()
|
using TRangedForIterator = TBaseIterator<false, true>;
|
||||||
|
using TRangedForConstIterator = TBaseIterator<true, true>;
|
||||||
|
|
||||||
|
/** Iterates over values associated with a specified key in a const map. */
|
||||||
|
class TConstKeyIterator : public TBaseKeyIterator<true>
|
||||||
{
|
{
|
||||||
return TMap<KeyType, ValueType>::FBaseIterator(*this, Pairs.begin());
|
public:
|
||||||
}
|
FORCEINLINE TConstKeyIterator(const TMapBase& InMap, KeyInitType InKey)
|
||||||
FORCEINLINE const TMap<KeyType, ValueType>::FBaseIterator begin() const
|
: TBaseKeyIterator<true>(typename ElementSetType::TConstKeyIterator(InMap.Pairs, InKey))
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Iterates over values associated with a specified key in a map. */
|
||||||
|
class TKeyIterator : public TBaseKeyIterator<false>
|
||||||
{
|
{
|
||||||
return TMap<KeyType, ValueType>::FBaseIterator(*this, Pairs.begin());
|
public:
|
||||||
}
|
FORCEINLINE TKeyIterator(TMapBase& InMap, KeyInitType InKey)
|
||||||
FORCEINLINE TMap<KeyType, ValueType>::FBaseIterator end()
|
: TBaseKeyIterator<false>(typename ElementSetType::TKeyIterator(InMap.Pairs, InKey))
|
||||||
|
{}
|
||||||
|
|
||||||
|
/** Removes the current key-value pair from the map. */
|
||||||
|
FORCEINLINE void RemoveCurrent()
|
||||||
{
|
{
|
||||||
return TMap<KeyType, ValueType>::FBaseIterator(*this, Pairs.end());
|
TBaseKeyIterator<false>::SetIt.RemoveCurrent();
|
||||||
}
|
}
|
||||||
FORCEINLINE const TMap<KeyType, ValueType>::FBaseIterator end() const
|
};
|
||||||
|
|
||||||
|
/** Creates an iterator over all the pairs in this map */
|
||||||
|
FORCEINLINE TIterator CreateIterator()
|
||||||
{
|
{
|
||||||
return TMap<KeyType, ValueType>::FBaseIterator(*this, Pairs.end());
|
return TIterator(*this);
|
||||||
}
|
}
|
||||||
FORCEINLINE ValueType& operator[](const KeyType& Key)
|
|
||||||
|
/** Creates a const iterator over all the pairs in this map */
|
||||||
|
FORCEINLINE TConstIterator CreateConstIterator() const
|
||||||
{
|
{
|
||||||
return this->GetByKey(Key);
|
return TConstIterator(*this);
|
||||||
}
|
}
|
||||||
FORCEINLINE const ValueType& operator[](const KeyType& Key) const
|
|
||||||
|
/** Creates an iterator over the values associated with a specified key in a map */
|
||||||
|
FORCEINLINE TKeyIterator CreateKeyIterator(KeyInitType InKey)
|
||||||
{
|
{
|
||||||
return this->GetByKey(Key);
|
return TKeyIterator(*this, InKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Creates a const iterator over the values associated with a specified key in a map */
|
||||||
|
FORCEINLINE TConstKeyIterator CreateConstKeyIterator(KeyInitType InKey) const
|
||||||
|
{
|
||||||
|
return TConstKeyIterator(*this, InKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE ValueType* Find(KeyConstPointerType Key)
|
||||||
|
{
|
||||||
|
if (auto* Pair = Pairs.Find(Key))
|
||||||
|
{
|
||||||
|
return &Pair->Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE const ValueType& FindChecked(KeyConstPointerType Key) const
|
||||||
|
{
|
||||||
|
const auto* Pair = Pairs.Find(Key);
|
||||||
|
// check(Pair != nullptr);
|
||||||
|
return Pair->Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a reference to the value associated with a specified key.
|
||||||
|
*
|
||||||
|
* @param Key The key to search for.
|
||||||
|
* @return The value associated with the specified key, or triggers an assertion if the key does not exist.
|
||||||
|
*/
|
||||||
|
FORCEINLINE ValueType& FindChecked(KeyConstPointerType Key)
|
||||||
|
{
|
||||||
|
auto* Pair = Pairs.Find(Key);
|
||||||
|
// check(Pair != nullptr);
|
||||||
|
return Pair->Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE ValueType FindRef(KeyConstPointerType Key) const
|
||||||
|
{
|
||||||
|
if (const auto* Pair = Pairs.Find(Key))
|
||||||
|
{
|
||||||
|
return Pair->Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ValueType();
|
||||||
|
}
|
||||||
|
|
||||||
FORCEINLINE int32 Num() const
|
FORCEINLINE int32 Num() const
|
||||||
{
|
{
|
||||||
return Pairs.Num();
|
return Pairs.Num();
|
||||||
}
|
}
|
||||||
FORCEINLINE bool IsValid() const
|
|
||||||
{
|
|
||||||
return Pairs.IsValid();
|
|
||||||
}
|
|
||||||
FORCEINLINE bool IsIndexValid(int32 IndexToCheck) const
|
|
||||||
{
|
|
||||||
return Pairs.IsIndexValid(IndexToCheck);
|
|
||||||
}
|
|
||||||
FORCEINLINE bool Contains(const KeyType& ElementToLookFor) const
|
|
||||||
{
|
|
||||||
for (auto& Element : *this)
|
|
||||||
{
|
|
||||||
if (Element.Key() == ElementToLookFor)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
FORCEINLINE ValueType& GetByKey(const KeyType& Key, bool* wasSuccessful = nullptr)
|
|
||||||
{
|
|
||||||
for (auto& Pair : *this)
|
|
||||||
{
|
|
||||||
if (Pair.Key() == Key)
|
|
||||||
{
|
|
||||||
if (wasSuccessful)
|
|
||||||
*wasSuccessful = true;
|
|
||||||
|
|
||||||
return Pair.Value();
|
private:
|
||||||
}
|
/**
|
||||||
}
|
* DO NOT USE DIRECTLY
|
||||||
|
* STL-like iterators to enable range-based for loop support.
|
||||||
// LOG_INFO(LogDev, "Failed to find Key!!!");
|
*/
|
||||||
|
FORCEINLINE friend TRangedForIterator begin(TMapBase& MapBase) { return TRangedForIterator(begin(MapBase.Pairs)); }
|
||||||
if (wasSuccessful)
|
FORCEINLINE friend TRangedForConstIterator begin(const TMapBase& MapBase) { return TRangedForConstIterator(begin(MapBase.Pairs)); }
|
||||||
*wasSuccessful = false;
|
FORCEINLINE friend TRangedForIterator end(TMapBase& MapBase) { return TRangedForIterator(end(MapBase.Pairs)); }
|
||||||
}
|
FORCEINLINE friend TRangedForConstIterator end(const TMapBase& MapBase) { return TRangedForConstIterator(end(MapBase.Pairs)); }
|
||||||
FORCEINLINE ValueType& Find(const KeyType& Key, bool* wasSuccessful = nullptr)
|
};
|
||||||
{
|
|
||||||
return GetByKey(Key, wasSuccessful);
|
template <typename KeyType, typename ValueType, typename SetAllocator, typename KeyFuncs>
|
||||||
}
|
class TSortableMapBase : public TMapBase<KeyType, ValueType, SetAllocator, KeyFuncs>
|
||||||
FORCEINLINE ValueType GetByKeyNoRef(const KeyType& Key)
|
{
|
||||||
{
|
// friend struct TContainerTraits<TSortableMapBase>;
|
||||||
for (auto& Pair : *this)
|
|
||||||
{
|
protected:
|
||||||
if (Pair.Key() == Key)
|
typedef TMapBase<KeyType, ValueType, SetAllocator, KeyFuncs> Super;
|
||||||
{
|
|
||||||
return Pair.Value();
|
TSortableMapBase() = default;
|
||||||
}
|
TSortableMapBase(TSortableMapBase&&) = default;
|
||||||
}
|
TSortableMapBase(const TSortableMapBase&) = default;
|
||||||
}
|
TSortableMapBase& operator=(TSortableMapBase&&) = default;
|
||||||
|
TSortableMapBase& operator=(const TSortableMapBase&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename KeyType, typename ValueType, typename SetAllocator = FDefaultSetAllocator, typename KeyFuncs = TDefaultMapHashableKeyFuncs<KeyType,ValueType,false>>
|
||||||
|
class TMap : public TSortableMapBase<KeyType, ValueType, SetAllocator, KeyFuncs>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef TSortableMapBase<KeyType, ValueType, SetAllocator, KeyFuncs> Super;
|
||||||
|
typedef typename Super::KeyInitType KeyInitType;
|
||||||
|
typedef typename Super::KeyConstPointerType KeyConstPointerType;
|
||||||
|
|
||||||
|
typedef TPair<KeyType, ValueType> ElementType;
|
||||||
|
public:
|
||||||
|
typedef TSet<ElementType, KeyFuncs, SetAllocator> ElementSetType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TMap() = default;
|
||||||
|
TMap(TMap&&) = default;
|
||||||
|
TMap(const TMap&) = default;
|
||||||
|
TMap& operator=(TMap&&) = default;
|
||||||
|
TMap& operator=(const TMap&) = default;
|
||||||
};
|
};
|
||||||
@@ -77,3 +77,10 @@ struct FName
|
|||||||
return GetComparisonIndexFast() < Rhs.GetComparisonIndexFast();
|
return GetComparisonIndexFast() < Rhs.GetComparisonIndexFast();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline uint32 GetTypeHash(const FName N)
|
||||||
|
{
|
||||||
|
return N.ComparisonIndex.Value + N.GetNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NAME_None FName(0);
|
||||||
@@ -6,10 +6,37 @@
|
|||||||
#include "WeakObjectPtrTemplates.h"
|
#include "WeakObjectPtrTemplates.h"
|
||||||
#include "ActorChannel.h"
|
#include "ActorChannel.h"
|
||||||
#include <memcury.h>
|
#include <memcury.h>
|
||||||
|
#include "KismetStringLibrary.h"
|
||||||
|
|
||||||
class UNetConnection : public UPlayer
|
class UNetConnection : public UPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static inline UChannel* (*originalCreateChannel)(UNetConnection*, int, bool, int32_t);
|
||||||
|
static inline UChannel* (*originalCreateChannelByName)(UNetConnection* Connection, FName* ChName, EChannelCreateFlags CreateFlags, int32_t ChannelIndex);
|
||||||
|
|
||||||
|
TSet<FNetworkGUID>& GetDestroyedStartupOrDormantActors() // T(REP)
|
||||||
|
{
|
||||||
|
static int off = Fortnite_Version == 1.11 ? 0x33678 : 0;
|
||||||
|
|
||||||
|
return *(TSet<FNetworkGUID>*)(__int64(this) + off);
|
||||||
|
}
|
||||||
|
|
||||||
|
UChannel* CreateChannel(EChannelType ChannelType, bool bOpenedLocally, EChannelCreateFlags CreateFlags, int32 ChannelIndex = INDEX_NONE)
|
||||||
|
{
|
||||||
|
if (Engine_Version >= 422)
|
||||||
|
{
|
||||||
|
FString ActorStr = L"Actor";
|
||||||
|
FName ActorName = UKismetStringLibrary::Conv_StringToName(ActorStr);
|
||||||
|
|
||||||
|
int ChannelIndex = -1; // 4294967295
|
||||||
|
return (UActorChannel*)originalCreateChannelByName(this, &ActorName, CreateFlags, ChannelIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (UActorChannel*)originalCreateChannel(this, ChannelType, bOpenedLocally, ChannelIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AActor*& GetOwningActor()
|
AActor*& GetOwningActor()
|
||||||
{
|
{
|
||||||
static auto OwningActorOffset = GetOffset("OwningActor");
|
static auto OwningActorOffset = GetOffset("OwningActor");
|
||||||
@@ -22,13 +49,24 @@ public:
|
|||||||
return *(FName*)(__int64(this) + ClientWorldPackageNameOffset);
|
return *(FName*)(__int64(this) + ClientWorldPackageNameOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
AActor*& GetViewTarget()
|
inline AActor*& GetViewTarget()
|
||||||
{
|
{
|
||||||
static auto ViewTargetOffset = GetOffset("ViewTarget");
|
static auto ViewTargetOffset = GetOffset("ViewTarget");
|
||||||
return Get<AActor*>(ViewTargetOffset);
|
return Get<AActor*>(ViewTargetOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 IsNetReady(bool Saturate)
|
bool& GetTimeSensitive() // T(REP)
|
||||||
|
{
|
||||||
|
return *(bool*)(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<class UChildConnection*>& GetChildren()
|
||||||
|
{
|
||||||
|
static auto ChildrenOffset = GetOffset("Children");
|
||||||
|
return Get<TArray<class UChildConnection*>>(ChildrenOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 IsNetReady(bool Saturate) // T(REP)
|
||||||
{
|
{
|
||||||
static auto IsNetReadyOffset = 0x298; // 1.11
|
static auto IsNetReadyOffset = 0x298; // 1.11
|
||||||
int32 (*IsNetReadyOriginal)(UNetConnection* Connection, bool Saturate) = decltype(IsNetReadyOriginal)(this->VFTable[IsNetReadyOffset / 8]);
|
int32 (*IsNetReadyOriginal)(UNetConnection* Connection, bool Saturate) = decltype(IsNetReadyOriginal)(this->VFTable[IsNetReadyOffset / 8]);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -56,15 +56,6 @@ struct FNetworkObjectInfo
|
|||||||
TSet<TWeakObjectPtr<UNetConnection>> RecentlyDormantConnections;
|
TSet<TWeakObjectPtr<UNetConnection>> RecentlyDormantConnections;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FNetViewer
|
|
||||||
{
|
|
||||||
UNetConnection* Connection; // 0x0000(0x0008) (ZeroConstructor, IsPlainOldData)
|
|
||||||
AActor* InViewer; // 0x0008(0x0008) (ZeroConstructor, IsPlainOldData)
|
|
||||||
AActor* ViewTarget; // 0x0010(0x0008) (ZeroConstructor, IsPlainOldData)
|
|
||||||
FVector ViewLocation; // 0x0018(0x000C) (IsPlainOldData)
|
|
||||||
FVector ViewDir;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FNetworkObjectList
|
class FNetworkObjectList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -77,6 +68,7 @@ public:
|
|||||||
TMap<TWeakObjectPtr<UNetConnection>, int32> NumDormantObjectsPerConnection;
|
TMap<TWeakObjectPtr<UNetConnection>, int32> NumDormantObjectsPerConnection;
|
||||||
|
|
||||||
void Remove(AActor* const Actor);
|
void Remove(AActor* const Actor);
|
||||||
|
const FNetworkObjectSet& GetActiveObjects() const { return ActiveNetworkObjects; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FActorPriority
|
struct FActorPriority
|
||||||
@@ -130,6 +122,13 @@ public:
|
|||||||
|
|
||||||
static void TickFlushHook(UNetDriver* NetDriver);
|
static void TickFlushHook(UNetDriver* NetDriver);
|
||||||
|
|
||||||
|
TMap<FNetworkGUID, FActorDestructionInfo>& GetDestroyedStartupOrDormantActors() // T(REP)
|
||||||
|
{
|
||||||
|
static int off = Fortnite_Version == 1.11 ? 0x228 : 0; // 0x240
|
||||||
|
|
||||||
|
return *(TMap<FNetworkGUID, FActorDestructionInfo>*)(__int64(this) + off);
|
||||||
|
}
|
||||||
|
|
||||||
int& GetMaxInternetClientRate()
|
int& GetMaxInternetClientRate()
|
||||||
{
|
{
|
||||||
static auto MaxInternetClientRateOffset = GetOffset("MaxInternetClientRate");
|
static auto MaxInternetClientRateOffset = GetOffset("MaxInternetClientRate");
|
||||||
@@ -142,13 +141,19 @@ public:
|
|||||||
return Get<int>(MaxClientRateOffset);
|
return Get<int>(MaxClientRateOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FName& GetNetDriverName()
|
||||||
|
{
|
||||||
|
static auto NetDriverNameOffset = GetOffset("NetDriverName");
|
||||||
|
return Get<FName>(NetDriverNameOffset);
|
||||||
|
}
|
||||||
|
|
||||||
FNetGUIDCache* GetGuidCache()
|
FNetGUIDCache* GetGuidCache()
|
||||||
{
|
{
|
||||||
static auto GuidCacheOffset = GetOffset("WorldPackage") + 8; // checked for 1.11
|
static auto GuidCacheOffset = GetOffset("WorldPackage") + 8; // checked for 1.11
|
||||||
return GetPtr<FNetGUIDCache>(GuidCacheOffset);
|
return GetPtr<FNetGUIDCache>(GuidCacheOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
UWorld*& GetNetDriverWorld() const
|
UWorld*& World() const
|
||||||
{
|
{
|
||||||
static auto WorldOffset = GetOffset("World");
|
static auto WorldOffset = GetOffset("World");
|
||||||
return Get<UWorld*>(WorldOffset);
|
return Get<UWorld*>(WorldOffset);
|
||||||
@@ -195,8 +200,9 @@ public:
|
|||||||
bool InitListen(FNetworkNotify* InNotify, FURL& ListenURL, bool bReuseAddressAndPort, FString& Error) { return InitListenOriginal(this, InNotify, ListenURL, bReuseAddressAndPort, Error); }
|
bool InitListen(FNetworkNotify* InNotify, FURL& ListenURL, bool bReuseAddressAndPort, FString& Error) { return InitListenOriginal(this, InNotify, ListenURL, bReuseAddressAndPort, Error); }
|
||||||
void SetWorld(UWorld* World) { return SetWorldOriginal(this, World); }
|
void SetWorld(UWorld* World) { return SetWorldOriginal(this, World); }
|
||||||
int32 ServerReplicateActors();
|
int32 ServerReplicateActors();
|
||||||
int32 ServerReplicateActors_ProcessPrioritizedActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, FActorPriority** PriorityActors, const int32 FinalSortedCount, int32& OutUpdated);
|
int32 ServerReplicateActors_PrepConnections();
|
||||||
|
int32 ServerReplicateActors_ProcessPrioritizedActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, std::vector<FActorPriority*>& PriorityActors, const int32 FinalSortedCount, int32& OutUpdated);
|
||||||
void ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList, const float ServerTickTime);
|
void ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList, const float ServerTickTime);
|
||||||
int32 ServerReplicateActors_PrioritizeActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, const std::vector<FNetworkObjectInfo*> ConsiderList, const bool bCPUSaturated, FActorPriority*& OutPriorityList, FActorPriority**& OutPriorityActors);
|
int32 ServerReplicateActors_PrioritizeActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, const std::vector<FNetworkObjectInfo*>& ConsiderList, const bool bCPUSaturated, std::vector<FActorPriority>& OutPriorityList, std::vector<FActorPriority*>& OutPriorityActors);
|
||||||
FNetworkObjectList& GetNetworkObjectList();
|
FNetworkObjectList& GetNetworkObjectList();
|
||||||
};
|
};
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "NetDriver.h"
|
#include "NetDriver.h"
|
||||||
|
|
||||||
void FNetworkObjectList::Remove(AActor* const Actor)
|
void FNetworkObjectList::Remove(AActor* const Actor) // T(REP)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
if (Actor == nullptr)
|
if (Actor == nullptr)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -103,5 +104,7 @@ void FNetworkObjectList::Remove(AActor* const Actor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// check((ActiveNetworkObjects.Num() + ObjectsDormantOnAllConnections.Num()) == AllNetworkObjects.Num());
|
// check((ActiveNetworkObjects.Num() + ObjectsDormantOnAllConnections.Num()) == AllNetworkObjects.Num());
|
||||||
}
|
}
|
||||||
11
Project Reboot 3.0/NetworkingDistanceConstants.h
Normal file
11
Project Reboot 3.0/NetworkingDistanceConstants.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// magic number distances used by AI/networking
|
||||||
|
#define CLOSEPROXIMITY 500.f
|
||||||
|
#define NEARSIGHTTHRESHOLD 2000.f
|
||||||
|
#define MEDSIGHTTHRESHOLD 3162.f
|
||||||
|
#define FARSIGHTTHRESHOLD 8000.f
|
||||||
|
#define CLOSEPROXIMITYSQUARED (CLOSEPROXIMITY*CLOSEPROXIMITY)
|
||||||
|
#define NEARSIGHTTHRESHOLDSQUARED (NEARSIGHTTHRESHOLD*NEARSIGHTTHRESHOLD)
|
||||||
|
#define MEDSIGHTTHRESHOLDSQUARED (MEDSIGHTTHRESHOLD*MEDSIGHTTHRESHOLD)
|
||||||
|
#define FARSIGHTTHRESHOLDSQUARED (FARSIGHTTHRESHOLD*FARSIGHTTHRESHOLD)
|
||||||
@@ -7,6 +7,21 @@
|
|||||||
#include "UObjectArray.h"
|
#include "UObjectArray.h"
|
||||||
#include "Package.h"
|
#include "Package.h"
|
||||||
|
|
||||||
|
UObject* UObject::GetTypedOuter(UClass* Target) const
|
||||||
|
{
|
||||||
|
// ensureMsgf(Target != UPackage::StaticClass(), TEXT("Calling GetTypedOuter to retrieve a package is now invalid, you should use GetPackage() instead."));
|
||||||
|
|
||||||
|
UObject* Result = NULL;
|
||||||
|
for (UObject* NextOuter = GetOuter(); Result == NULL && NextOuter != NULL; NextOuter = NextOuter->GetOuter())
|
||||||
|
{
|
||||||
|
if (NextOuter->IsA(Target))
|
||||||
|
{
|
||||||
|
Result = NextOuter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
void* UObject::GetProperty(const std::string& ChildName, bool bWarnIfNotFound) const
|
void* UObject::GetProperty(const std::string& ChildName, bool bWarnIfNotFound) const
|
||||||
{
|
{
|
||||||
for (auto CurrentClass = ClassPrivate; CurrentClass; CurrentClass = *(UClass**)(__int64(CurrentClass) + Offsets::SuperStruct))
|
for (auto CurrentClass = ClassPrivate; CurrentClass; CurrentClass = *(UClass**)(__int64(CurrentClass) + Offsets::SuperStruct))
|
||||||
|
|||||||
@@ -78,6 +78,14 @@ public:
|
|||||||
void SetBitfieldValue(int Offset, uint8_t FieldMask, bool NewValue);
|
void SetBitfieldValue(int Offset, uint8_t FieldMask, bool NewValue);
|
||||||
void SetBitfieldValue(const std::string& ChildName, uint8_t FieldMask, bool NewValue) { return SetBitfieldValue(GetOffset(ChildName), FieldMask, NewValue); }
|
void SetBitfieldValue(const std::string& ChildName, uint8_t FieldMask, bool NewValue) { return SetBitfieldValue(GetOffset(ChildName), FieldMask, NewValue); }
|
||||||
|
|
||||||
|
UObject* GetTypedOuter(UClass* Target) const;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* GetTypedOuter() const
|
||||||
|
{
|
||||||
|
return (T*)GetTypedOuter(T::StaticClass());
|
||||||
|
}
|
||||||
|
|
||||||
/* template <typename T = UObject*>
|
/* template <typename T = UObject*>
|
||||||
T& GetCached(const std::string& ChildName)
|
T& GetCached(const std::string& ChildName)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
class APlayerController : public AController
|
class APlayerController : public AController
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static inline void (*originalSendClientAdjustment)(APlayerController*);
|
||||||
|
|
||||||
UCheatManager*& GetCheatManager()
|
UCheatManager*& GetCheatManager()
|
||||||
{
|
{
|
||||||
static auto CheatManagerOffset = this->GetOffset("CheatManager");
|
static auto CheatManagerOffset = this->GetOffset("CheatManager");
|
||||||
|
|||||||
@@ -308,6 +308,8 @@
|
|||||||
<ClInclude Include="BuildingTrap.h" />
|
<ClInclude Include="BuildingTrap.h" />
|
||||||
<ClInclude Include="Channel.h" />
|
<ClInclude Include="Channel.h" />
|
||||||
<ClInclude Include="CheatManager.h" />
|
<ClInclude Include="CheatManager.h" />
|
||||||
|
<ClInclude Include="ChildConnection.h" />
|
||||||
|
<ClInclude Include="ChooseClass.h" />
|
||||||
<ClInclude Include="Class.h" />
|
<ClInclude Include="Class.h" />
|
||||||
<ClInclude Include="commands.h" />
|
<ClInclude Include="commands.h" />
|
||||||
<ClInclude Include="ContainerAllocationPolicies.h" />
|
<ClInclude Include="ContainerAllocationPolicies.h" />
|
||||||
@@ -446,6 +448,7 @@
|
|||||||
<ClInclude Include="NetDriver.h" />
|
<ClInclude Include="NetDriver.h" />
|
||||||
<ClInclude Include="NetSerialization.h" />
|
<ClInclude Include="NetSerialization.h" />
|
||||||
<ClInclude Include="NetworkGuid.h" />
|
<ClInclude Include="NetworkGuid.h" />
|
||||||
|
<ClInclude Include="NetworkingDistanceConstants.h" />
|
||||||
<ClInclude Include="NumericLimits.h" />
|
<ClInclude Include="NumericLimits.h" />
|
||||||
<ClInclude Include="Object.h" />
|
<ClInclude Include="Object.h" />
|
||||||
<ClInclude Include="ObjectMacros.h" />
|
<ClInclude Include="ObjectMacros.h" />
|
||||||
@@ -499,6 +502,7 @@
|
|||||||
<ClInclude Include="WeakObjectPtr.h" />
|
<ClInclude Include="WeakObjectPtr.h" />
|
||||||
<ClInclude Include="WeakObjectPtrTemplates.h" />
|
<ClInclude Include="WeakObjectPtrTemplates.h" />
|
||||||
<ClInclude Include="World.h" />
|
<ClInclude Include="World.h" />
|
||||||
|
<ClInclude Include="WorldSettings.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="DelegateSignatureImpl.inl" />
|
<None Include="DelegateSignatureImpl.inl" />
|
||||||
|
|||||||
@@ -987,6 +987,18 @@
|
|||||||
<ClInclude Include="botnames.h">
|
<ClInclude Include="botnames.h">
|
||||||
<Filter>Reboot\Public</Filter>
|
<Filter>Reboot\Public</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="ChildConnection.h">
|
||||||
|
<Filter>Engine\Source\Runtime\Engine\Classes\Engine</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="WorldSettings.h">
|
||||||
|
<Filter>Engine\Source\Runtime\Engine\Classes\GameFramework</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ChooseClass.h">
|
||||||
|
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="NetworkingDistanceConstants.h">
|
||||||
|
<Filter>Engine\Source\Runtime\Engine\Public</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Engine">
|
<Filter Include="Engine">
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
|
// Copied from 4.19
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SparseArray.h"
|
#include "SparseArray.h"
|
||||||
|
#include "ChooseClass.h"
|
||||||
|
#include "UnrealTypeTraits.h"
|
||||||
|
|
||||||
template <typename ElementType>
|
template <typename ElementType>
|
||||||
class TSetElement
|
class TSetElement
|
||||||
@@ -32,112 +36,434 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename SetType>
|
/** Either NULL or an identifier for an element of a set. */
|
||||||
|
class FSetElementId
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
template<typename, typename, typename>
|
||||||
|
friend class TSet;
|
||||||
|
|
||||||
|
friend class FScriptSet;
|
||||||
|
|
||||||
|
/** Default constructor. */
|
||||||
|
FORCEINLINE FSetElementId() :
|
||||||
|
Index(INDEX_NONE)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/** @return a boolean value representing whether the id is NULL. */
|
||||||
|
FORCEINLINE bool IsValidId() const
|
||||||
|
{
|
||||||
|
return Index != INDEX_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Comparison operator. */
|
||||||
|
FORCEINLINE friend bool operator==(const FSetElementId& A, const FSetElementId& B)
|
||||||
|
{
|
||||||
|
return A.Index == B.Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 AsInteger() const
|
||||||
|
{
|
||||||
|
return Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE static FSetElementId FromInteger(int32 Integer)
|
||||||
|
{
|
||||||
|
return FSetElementId(Integer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** The index of the element in the set's element array. */
|
||||||
|
int32 Index;
|
||||||
|
|
||||||
|
/** Initialization constructor. */
|
||||||
|
FORCEINLINE FSetElementId(int32 InIndex) :
|
||||||
|
Index(InIndex)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/** Implicit conversion to the element index. */
|
||||||
|
FORCEINLINE operator int32() const
|
||||||
|
{
|
||||||
|
return Index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ElementType, typename InKeyType, bool bInAllowDuplicateKeys = false>
|
||||||
|
struct BaseKeyFuncs
|
||||||
|
{
|
||||||
|
typedef InKeyType KeyType;
|
||||||
|
typedef typename TCallTraits<InKeyType>::ParamType KeyInitType;
|
||||||
|
typedef typename TCallTraits<ElementType>::ParamType ElementInitType;
|
||||||
|
|
||||||
|
enum { bAllowDuplicateKeys = bInAllowDuplicateKeys };
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A default implementation of the KeyFuncs used by TSet which uses the element as a key.
|
||||||
|
*/
|
||||||
|
template<typename ElementType, bool bInAllowDuplicateKeys = false>
|
||||||
|
struct DefaultKeyFuncs : BaseKeyFuncs<ElementType, ElementType, bInAllowDuplicateKeys>
|
||||||
|
{
|
||||||
|
typedef typename TCallTraits<ElementType>::ParamType KeyInitType;
|
||||||
|
typedef typename TCallTraits<ElementType>::ParamType ElementInitType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The key used to index the given element.
|
||||||
|
*/
|
||||||
|
static FORCEINLINE KeyInitType GetSetKey(ElementInitType Element)
|
||||||
|
{
|
||||||
|
return Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if the keys match.
|
||||||
|
*/
|
||||||
|
static FORCEINLINE bool Matches(KeyInitType A, KeyInitType B)
|
||||||
|
{
|
||||||
|
return A == B;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Calculates a hash index for a key. */
|
||||||
|
static FORCEINLINE uint32 GetKeyHash(KeyInitType Key)
|
||||||
|
{
|
||||||
|
return GetTypeHash(Key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename InElementType,
|
||||||
|
typename KeyFuncs = DefaultKeyFuncs<InElementType>,
|
||||||
|
typename Allocator = FDefaultSetAllocator
|
||||||
|
>
|
||||||
|
class TSet;
|
||||||
|
|
||||||
|
template<
|
||||||
|
typename InElementType,
|
||||||
|
typename KeyFuncs /*= DefaultKeyFuncs<ElementType>*/,
|
||||||
|
typename Allocator /*= FDefaultSetAllocator*/
|
||||||
|
>
|
||||||
class TSet
|
class TSet
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
friend TSparseArray;
|
friend TSparseArray;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef TSetElement<SetType> ElementType;
|
typedef typename KeyFuncs::KeyInitType KeyInitType;
|
||||||
typedef TSparseArrayElementOrListLink<ElementType> ArrayElementType;
|
typedef typename KeyFuncs::ElementInitType ElementInitType;
|
||||||
|
|
||||||
|
typedef TSetElement<InElementType> SetElementType;
|
||||||
|
|
||||||
|
typedef InElementType ElementType;
|
||||||
public:
|
public:
|
||||||
TSparseArray<ElementType> Elements;
|
typedef TSparseArray<SetElementType, typename Allocator::SparseArrayAllocator> ElementArrayType;
|
||||||
|
typedef typename Allocator::HashAllocator::template ForElementType<FSetElementId> HashType;
|
||||||
|
|
||||||
mutable TInlineAllocator<1>::ForElementType<int> Hash;
|
ElementArrayType Elements;
|
||||||
|
|
||||||
|
mutable HashType Hash;
|
||||||
mutable int32 HashSize;
|
mutable int32 HashSize;
|
||||||
|
|
||||||
|
FORCEINLINE FSetElementId& GetTypedHash(int32 HashIndex) const
|
||||||
|
{
|
||||||
|
return ((FSetElementId*)Hash.GetAllocation())[HashIndex & (HashSize - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class FBaseIterator
|
FORCEINLINE ElementType* Find(KeyInitType Key)
|
||||||
|
{
|
||||||
|
FSetElementId ElementId = FindId(Key);
|
||||||
|
if (ElementId.IsValidId())
|
||||||
|
{
|
||||||
|
return &Elements[ElementId].Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds an element with the given key in the set.
|
||||||
|
* @param Key - The key to search for.
|
||||||
|
* @return A const pointer to an element with the given key. If no element in the set has the given key, this will return NULL.
|
||||||
|
*/
|
||||||
|
FORCEINLINE const ElementType* Find(KeyInitType Key) const
|
||||||
|
{
|
||||||
|
FSetElementId ElementId = FindId(Key);
|
||||||
|
if (ElementId.IsValidId())
|
||||||
|
{
|
||||||
|
return &Elements[ElementId].Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Adds an element to the hash. */
|
||||||
|
FORCEINLINE void HashElement(FSetElementId ElementId, const SetElementType& Element) const
|
||||||
|
{
|
||||||
|
// Compute the hash bucket the element goes in.
|
||||||
|
Element.HashIndex = KeyFuncs::GetKeyHash(KeyFuncs::GetSetKey(Element.Value)) & (HashSize - 1);
|
||||||
|
|
||||||
|
// Link the element into the hash bucket.
|
||||||
|
Element.HashNextId = GetTypedHash(Element.HashIndex);
|
||||||
|
GetTypedHash(Element.HashIndex) = ElementId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the hash has an appropriate number of buckets, and if not resizes it.
|
||||||
|
* @param NumHashedElements - The number of elements to size the hash for.
|
||||||
|
* @param bAllowShrinking - true if the hash is allowed to shrink.
|
||||||
|
* @return true if the set was rehashed.
|
||||||
|
*/
|
||||||
|
bool ConditionalRehash(int32 NumHashedElements, bool bAllowShrinking = false) const
|
||||||
|
{
|
||||||
|
// Calculate the desired hash size for the specified number of elements.
|
||||||
|
const int32 DesiredHashSize = Allocator::GetNumberOfHashBuckets(NumHashedElements);
|
||||||
|
|
||||||
|
// If the hash hasn't been created yet, or is smaller than the desired hash size, rehash.
|
||||||
|
if (NumHashedElements > 0 &&
|
||||||
|
(!HashSize ||
|
||||||
|
HashSize < DesiredHashSize ||
|
||||||
|
(HashSize > DesiredHashSize && bAllowShrinking)))
|
||||||
|
{
|
||||||
|
HashSize = DesiredHashSize;
|
||||||
|
Rehash();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resizes the hash. */
|
||||||
|
void Rehash() const
|
||||||
|
{
|
||||||
|
// Free the old hash.
|
||||||
|
Hash.ResizeAllocation(0, 0, sizeof(FSetElementId));
|
||||||
|
|
||||||
|
int32 LocalHashSize = HashSize;
|
||||||
|
if (LocalHashSize)
|
||||||
|
{
|
||||||
|
// Allocate the new hash.
|
||||||
|
// checkSlow(FMath::IsPowerOfTwo(HashSize));
|
||||||
|
Hash.ResizeAllocation(0, LocalHashSize, sizeof(FSetElementId));
|
||||||
|
for (int32 HashIndex = 0; HashIndex < LocalHashSize; ++HashIndex)
|
||||||
|
{
|
||||||
|
GetTypedHash(HashIndex) = FSetElementId();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the existing elements to the new hash.
|
||||||
|
for (typename ElementArrayType::TConstIterator ElementIt(Elements); ElementIt; ++ElementIt)
|
||||||
|
{
|
||||||
|
HashElement(FSetElementId(ElementIt.GetIndex()), *ElementIt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<bool bConst, bool bRangedFor = false>
|
||||||
|
class TBaseIterator
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
TSet<SetType>& IteratedSet;
|
friend class TSet;
|
||||||
TSparseArray<ElementType>::FBaseIterator ElementIt;
|
|
||||||
|
typedef typename TChooseClass<bConst, const ElementType, ElementType>::Result ItElementType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FORCEINLINE FBaseIterator(const TSet<SetType>& InSet, TSparseArray<TSetElement<SetType>>::FBaseIterator InElementIt)
|
typedef typename TChooseClass<
|
||||||
: IteratedSet(const_cast<TSet<SetType>&>(InSet))
|
bConst,
|
||||||
, ElementIt(InElementIt)
|
typename TChooseClass<bRangedFor, typename ElementArrayType::TRangedForConstIterator, typename ElementArrayType::TConstIterator>::Result,
|
||||||
|
typename TChooseClass<bRangedFor, typename ElementArrayType::TRangedForIterator, typename ElementArrayType::TIterator >::Result
|
||||||
|
>::Result ElementItType;
|
||||||
|
|
||||||
|
FORCEINLINE TBaseIterator(const ElementItType& InElementIt)
|
||||||
|
: ElementIt(InElementIt)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE explicit operator bool() const
|
/** Advances the iterator to the next element. */
|
||||||
{
|
FORCEINLINE TBaseIterator& operator++()
|
||||||
return (bool)ElementIt;
|
|
||||||
}
|
|
||||||
FORCEINLINE TSet<SetType>::FBaseIterator& operator++()
|
|
||||||
{
|
{
|
||||||
++ElementIt;
|
++ElementIt;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FORCEINLINE bool operator==(const TSet<SetType>::FBaseIterator& OtherIt) const
|
|
||||||
|
/** conversion to "bool" returning true if the iterator is valid. */
|
||||||
|
FORCEINLINE explicit operator bool() const
|
||||||
{
|
{
|
||||||
return ElementIt == OtherIt.ElementIt;
|
return !!ElementIt;
|
||||||
}
|
}
|
||||||
FORCEINLINE bool operator!=(const TSet<SetType>::FBaseIterator& OtherIt) const
|
/** inverse of the "bool" operator */
|
||||||
|
FORCEINLINE bool operator !() const
|
||||||
{
|
{
|
||||||
return ElementIt != OtherIt.ElementIt;
|
return !(bool)*this;
|
||||||
}
|
}
|
||||||
FORCEINLINE TSet<SetType>::FBaseIterator& operator=(TSet<SetType>::FBaseIterator& OtherIt)
|
|
||||||
|
// Accessors.
|
||||||
|
FORCEINLINE FSetElementId GetId() const
|
||||||
{
|
{
|
||||||
return ElementIt = OtherIt.ElementIt;
|
return TSet::IndexToId(ElementIt.GetIndex());
|
||||||
}
|
}
|
||||||
FORCEINLINE SetType& operator*()
|
FORCEINLINE ItElementType* operator->() const
|
||||||
{
|
{
|
||||||
return (*ElementIt).Value;
|
return &ElementIt->Value;
|
||||||
}
|
}
|
||||||
FORCEINLINE const SetType& operator*() const
|
FORCEINLINE ItElementType& operator*() const
|
||||||
{
|
{
|
||||||
return &((*ElementIt).Value);
|
return ElementIt->Value;
|
||||||
}
|
}
|
||||||
FORCEINLINE SetType* operator->()
|
|
||||||
|
FORCEINLINE friend bool operator==(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.ElementIt == Rhs.ElementIt; }
|
||||||
|
FORCEINLINE friend bool operator!=(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.ElementIt != Rhs.ElementIt; }
|
||||||
|
|
||||||
|
ElementItType ElementIt;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The base type of whole set iterators. */
|
||||||
|
template<bool bConst>
|
||||||
|
class TBaseKeyIterator
|
||||||
{
|
{
|
||||||
return &((*ElementIt).Value);
|
private:
|
||||||
|
typedef typename TChooseClass<bConst, const TSet, TSet>::Result SetType;
|
||||||
|
typedef typename TChooseClass<bConst, const ElementType, ElementType>::Result ItElementType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Initialization constructor. */
|
||||||
|
FORCEINLINE TBaseKeyIterator(SetType& InSet, KeyInitType InKey)
|
||||||
|
: Set(InSet)
|
||||||
|
, Key(InKey)
|
||||||
|
, Id()
|
||||||
|
{
|
||||||
|
// The set's hash needs to be initialized to find the elements with the specified key.
|
||||||
|
Set.ConditionalRehash(Set.Elements.Num());
|
||||||
|
if (Set.HashSize)
|
||||||
|
{
|
||||||
|
NextId = Set.GetTypedHash(KeyFuncs::GetKeyHash(Key));
|
||||||
|
++(*this);
|
||||||
}
|
}
|
||||||
FORCEINLINE const SetType* operator->() const
|
/* // Milxnor: This is only on newer builds?
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return &(*ElementIt).Value;
|
NextIndex = INDEX_NONE;
|
||||||
}
|
}
|
||||||
FORCEINLINE const int32 GetIndex() const
|
*/
|
||||||
{
|
|
||||||
return ElementIt.GetIndex();
|
|
||||||
}
|
}
|
||||||
FORCEINLINE ElementType& GetSetElement()
|
|
||||||
|
/** Advances the iterator to the next element. */
|
||||||
|
FORCEINLINE TBaseKeyIterator& operator++()
|
||||||
{
|
{
|
||||||
return *ElementIt;
|
Id = NextId;
|
||||||
|
|
||||||
|
while (Id.IsValidId())
|
||||||
|
{
|
||||||
|
NextId = Set.GetInternalElement(Id).HashNextId;
|
||||||
|
// checkSlow(Id != NextId);
|
||||||
|
|
||||||
|
if (KeyFuncs::Matches(KeyFuncs::GetSetKey(Set[Id]), Key))
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
FORCEINLINE const ElementType& GetSetElement() const
|
|
||||||
{
|
Id = NextId;
|
||||||
return *ElementIt;
|
|
||||||
}
|
}
|
||||||
FORCEINLINE bool IsElementValid() const
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** conversion to "bool" returning true if the iterator is valid. */
|
||||||
|
FORCEINLINE explicit operator bool() const
|
||||||
|
{
|
||||||
|
return Id.IsValidId();
|
||||||
|
}
|
||||||
|
/** inverse of the "bool" operator */
|
||||||
|
FORCEINLINE bool operator !() const
|
||||||
|
{
|
||||||
|
return !(bool)*this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accessors.
|
||||||
|
FORCEINLINE ItElementType* operator->() const
|
||||||
|
{
|
||||||
|
return &Set[Id];
|
||||||
|
}
|
||||||
|
FORCEINLINE ItElementType& operator*() const
|
||||||
|
{
|
||||||
|
return Set[Id];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SetType& Set;
|
||||||
|
typename TTypeTraits<typename KeyFuncs::KeyType>::ConstPointerType Key;
|
||||||
|
FSetElementId Id;
|
||||||
|
FSetElementId NextId;
|
||||||
|
};
|
||||||
|
|
||||||
|
FORCEINLINE const SetElementType& GetInternalElement(FSetElementId Id) const
|
||||||
|
{
|
||||||
|
return Elements[Id];
|
||||||
|
}
|
||||||
|
FORCEINLINE SetElementType& GetInternalElement(FSetElementId Id)
|
||||||
|
{
|
||||||
|
return Elements[Id];
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
class TConstIterator : public TBaseIterator<true>
|
||||||
|
{
|
||||||
|
friend class TSet;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE TConstIterator(const TSet& InSet)
|
||||||
|
: TBaseIterator<true>(begin(InSet.Elements))
|
||||||
{
|
{
|
||||||
return ElementIt.IsElementValid();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
class TIterator : public TBaseIterator<false>
|
||||||
FORCEINLINE TSet<SetType>::FBaseIterator begin()
|
|
||||||
{
|
{
|
||||||
return TSet<SetType>::FBaseIterator(*this, Elements.begin());
|
friend class TSet;
|
||||||
}
|
|
||||||
FORCEINLINE const TSet<SetType>::FBaseIterator begin() const
|
public:
|
||||||
|
FORCEINLINE TIterator(TSet& InSet)
|
||||||
|
: TBaseIterator<false>(begin(InSet.Elements))
|
||||||
|
, Set(InSet)
|
||||||
{
|
{
|
||||||
return TSet<SetType>::FBaseIterator(*this, Elements.begin());
|
|
||||||
}
|
|
||||||
FORCEINLINE TSet<SetType>::FBaseIterator end()
|
|
||||||
{
|
|
||||||
return TSet<SetType>::FBaseIterator(*this, Elements.end());
|
|
||||||
}
|
|
||||||
FORCEINLINE const TSet<SetType>::FBaseIterator end() const
|
|
||||||
{
|
|
||||||
return TSet<SetType>::FBaseIterator(*this, Elements.end());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE SetType& operator[](int Index)
|
/** Removes the current element from the set. */
|
||||||
|
/* // T(R)
|
||||||
|
FORCEINLINE void RemoveCurrent()
|
||||||
{
|
{
|
||||||
return Elements[Index].ElementData.Value;
|
Set.Remove(TBaseIterator<false>::GetId());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private:
|
||||||
|
TSet& Set;
|
||||||
|
};
|
||||||
|
|
||||||
|
using TRangedForConstIterator = TBaseIterator<true, true>;
|
||||||
|
using TRangedForIterator = TBaseIterator<false, true>;
|
||||||
|
|
||||||
|
static FORCEINLINE FSetElementId IndexToId(int32 Index)
|
||||||
|
{
|
||||||
|
return FSetElementId(Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates an iterator for the contents of this set */
|
||||||
|
FORCEINLINE TIterator CreateIterator()
|
||||||
|
{
|
||||||
|
return TIterator(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a const iterator for the contents of this set */
|
||||||
|
FORCEINLINE TConstIterator CreateConstIterator() const
|
||||||
|
{
|
||||||
|
return TConstIterator(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE int32 Num() const
|
FORCEINLINE int32 Num() const
|
||||||
@@ -156,65 +482,39 @@ public:
|
|||||||
{
|
{
|
||||||
return Elements;
|
return Elements;
|
||||||
}
|
}
|
||||||
FORCEINLINE const TBitArray& GetAllocationFlags() const
|
|
||||||
{
|
|
||||||
return Elements.GetAllocationFlags();
|
|
||||||
}
|
|
||||||
FORCEINLINE bool IsIndexValid(int32 IndexToCheck) const
|
FORCEINLINE bool IsIndexValid(int32 IndexToCheck) const
|
||||||
{
|
{
|
||||||
return Elements.IsIndexValid(IndexToCheck);
|
return Elements.IsIndexValid(IndexToCheck);
|
||||||
}
|
}
|
||||||
FORCEINLINE const bool Contains(const SetType& ElementToLookFor) const
|
FSetElementId FindId(KeyInitType Key) const
|
||||||
{
|
{
|
||||||
if (Num() <= 0)
|
if (Elements.Num())
|
||||||
return false;
|
|
||||||
|
|
||||||
for (SetType Element : *this)
|
|
||||||
{
|
{
|
||||||
if (Element == ElementToLookFor)
|
for (FSetElementId ElementId = GetTypedHash(KeyFuncs::GetKeyHash(Key));
|
||||||
return true;
|
ElementId.IsValidId();
|
||||||
|
ElementId = Elements[ElementId].HashNextId)
|
||||||
|
{
|
||||||
|
if (KeyFuncs::Matches(KeyFuncs::GetSetKey(Elements[ElementId].Value), Key))
|
||||||
|
{
|
||||||
|
return ElementId;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
FORCEINLINE const int32 Find(const SetType& ElementToLookFor) const
|
|
||||||
{
|
|
||||||
for (auto It = this->begin(); It != this->end(); ++It)
|
|
||||||
{
|
|
||||||
if (*It == ElementToLookFor)
|
|
||||||
{
|
|
||||||
return It.GetIndex();
|
|
||||||
}
|
}
|
||||||
|
return FSetElementId();
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
FORCEINLINE bool Contains(KeyInitType Key) const
|
||||||
}
|
|
||||||
FORCEINLINE bool Remove(const SetType& ElementToRemove)
|
|
||||||
{
|
{
|
||||||
auto Idx = Find(ElementToRemove);
|
return FindId(Key).IsValidId();
|
||||||
|
|
||||||
if (Idx == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Elements.RemoveAt(Idx);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
FORCEINLINE bool Remove(int Index)
|
|
||||||
{
|
|
||||||
Elements.RemoveAt(Index);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* DO NOT USE DIRECTLY
|
||||||
|
* STL-like iterators to enable range-based for loop support.
|
||||||
|
*/
|
||||||
|
FORCEINLINE friend TRangedForIterator begin(TSet& Set) { return TRangedForIterator(begin(Set.Elements)); }
|
||||||
|
FORCEINLINE friend TRangedForConstIterator begin(const TSet& Set) { return TRangedForConstIterator(begin(Set.Elements)); }
|
||||||
|
FORCEINLINE friend TRangedForIterator end(TSet& Set) { return TRangedForIterator(end(Set.Elements)); }
|
||||||
|
FORCEINLINE friend TRangedForConstIterator end(const TSet& Set) { return TRangedForConstIterator(end(Set.Elements)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* template<typename InElementType> //, typename KeyFuncs, typename Allocator>
|
|
||||||
class TSet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef TSetElement<InElementType> ElementType;
|
|
||||||
typedef TSparseArrayElementOrListLink<ElementType> ArrayElementType;
|
|
||||||
|
|
||||||
TSparseArray<ElementType> Elements;
|
|
||||||
|
|
||||||
mutable TInlineAllocator<1>::ForElementType<int> Hash;
|
|
||||||
mutable int32 HashSize;
|
|
||||||
}; */
|
|
||||||
@@ -2,259 +2,229 @@
|
|||||||
|
|
||||||
#include "Array.h"
|
#include "Array.h"
|
||||||
#include "BitArray.h"
|
#include "BitArray.h"
|
||||||
|
#include "ChooseClass.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "TypeCompatibleBytes.h"
|
||||||
|
|
||||||
#define INDEX_NONE -1
|
#define INDEX_NONE -1
|
||||||
|
|
||||||
template <typename ElementType>
|
template<typename ElementType>
|
||||||
union TSparseArrayElementOrListLink
|
union TSparseArrayElementOrFreeListLink
|
||||||
{
|
{
|
||||||
TSparseArrayElementOrListLink(ElementType& InElement)
|
|
||||||
: ElementData(InElement)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
TSparseArrayElementOrListLink(ElementType&& InElement)
|
|
||||||
: ElementData(InElement)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TSparseArrayElementOrListLink(int32 InPrevFree, int32 InNextFree)
|
|
||||||
: PrevFreeIndex(InPrevFree)
|
|
||||||
, NextFreeIndex(InNextFree)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TSparseArrayElementOrListLink<ElementType> operator=(const TSparseArrayElementOrListLink<ElementType>& Other)
|
|
||||||
{
|
|
||||||
return TSparseArrayElementOrListLink(Other.NextFreeIndex, Other.PrevFreeIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** If the element is allocated, its value is stored here. */
|
/** If the element is allocated, its value is stored here. */
|
||||||
ElementType ElementData;
|
ElementType ElementData;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/** If the element isn't allocated, this is a link to the previous element in the array's free list. */
|
/** If the element isn't allocated, this is a link to the previous element in the array's free list. */
|
||||||
int PrevFreeIndex;
|
int32 PrevFreeIndex;
|
||||||
|
|
||||||
/** If the element isn't allocated, this is a link to the next element in the array's free list. */
|
/** If the element isn't allocated, this is a link to the next element in the array's free list. */
|
||||||
int NextFreeIndex;
|
int32 NextFreeIndex;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ArrayType>
|
template<typename ElementType, typename Allocator = FDefaultSparseArrayAllocator >
|
||||||
|
class TSparseArray;
|
||||||
|
|
||||||
|
template<typename InElementType, typename Allocator>
|
||||||
class TSparseArray
|
class TSparseArray
|
||||||
{
|
{
|
||||||
public:
|
using ElementType = InElementType;
|
||||||
typedef TSparseArrayElementOrListLink<ArrayType> FSparseArrayElement;
|
|
||||||
|
|
||||||
TArray<FSparseArrayElement> Data;
|
public:
|
||||||
TBitArray AllocationFlags;
|
typedef TSparseArrayElementOrFreeListLink<
|
||||||
|
TAlignedBytes<sizeof(ElementType), alignof(ElementType)>
|
||||||
|
> FElementOrFreeListLink;
|
||||||
|
|
||||||
|
typedef TArray<FElementOrFreeListLink/*, typename Allocator::ElementAllocator*/> DataType;
|
||||||
|
DataType Data;
|
||||||
|
|
||||||
|
typedef TBitArray<typename Allocator::BitArrayAllocator> AllocationBitArrayType;
|
||||||
|
AllocationBitArrayType AllocationFlags;
|
||||||
|
|
||||||
|
/** The index of an unallocated element in the array that currently contains the head of the linked list of free elements. */
|
||||||
int32 FirstFreeIndex;
|
int32 FirstFreeIndex;
|
||||||
|
|
||||||
|
/** The number of elements in the free list. */
|
||||||
int32 NumFreeIndices;
|
int32 NumFreeIndices;
|
||||||
|
|
||||||
FORCEINLINE int32 Num() const
|
FORCEINLINE int32 Num() const
|
||||||
{
|
{
|
||||||
return Data.Num() - NumFreeIndices;
|
return Data.Num() - NumFreeIndices;
|
||||||
}
|
}
|
||||||
|
template<bool bConst>
|
||||||
class FBaseIterator
|
class TBaseIterator
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
typedef TConstSetBitIterator<typename Allocator::BitArrayAllocator> BitArrayItType;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TSparseArray<ArrayType>& IteratedArray;
|
typedef typename TChooseClass<bConst, const TSparseArray, TSparseArray>::Result ArrayType;
|
||||||
TBitArray::FSetBitIterator BitArrayIt;
|
typedef typename TChooseClass<bConst, const ElementType, ElementType>::Result ItElementType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FORCEINLINE FBaseIterator(const TSparseArray<ArrayType>& Array, const TBitArray::FSetBitIterator BitIterator)
|
explicit TBaseIterator(ArrayType& InArray, const BitArrayItType& InBitArrayIt)
|
||||||
: IteratedArray(const_cast<TSparseArray<ArrayType>&>(Array))
|
: Array(InArray)
|
||||||
, BitArrayIt(const_cast<TBitArray::FSetBitIterator&>(BitIterator))
|
, BitArrayIt(InBitArrayIt)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE explicit operator bool() const
|
FORCEINLINE TBaseIterator& operator++()
|
||||||
{
|
|
||||||
return (bool)BitArrayIt;
|
|
||||||
}
|
|
||||||
FORCEINLINE TSparseArray<ArrayType>::FBaseIterator& operator++()
|
|
||||||
{
|
{
|
||||||
|
// Iterate to the next set allocation flag.
|
||||||
++BitArrayIt;
|
++BitArrayIt;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
FORCEINLINE ArrayType& operator*()
|
|
||||||
|
FORCEINLINE int32 GetIndex() const { return BitArrayIt.GetIndex(); }
|
||||||
|
|
||||||
|
FORCEINLINE friend bool operator==(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.BitArrayIt == Rhs.BitArrayIt && &Lhs.Array == &Rhs.Array; }
|
||||||
|
FORCEINLINE friend bool operator!=(const TBaseIterator& Lhs, const TBaseIterator& Rhs) { return Lhs.BitArrayIt != Rhs.BitArrayIt || &Lhs.Array != &Rhs.Array; }
|
||||||
|
|
||||||
|
/** conversion to "bool" returning true if the iterator is valid. */
|
||||||
|
FORCEINLINE explicit operator bool() const
|
||||||
{
|
{
|
||||||
return IteratedArray[BitArrayIt.GetIndex()].ElementData;
|
return !!BitArrayIt;
|
||||||
}
|
|
||||||
FORCEINLINE const ArrayType& operator*() const
|
|
||||||
{
|
|
||||||
return IteratedArray[BitArrayIt.GetIndex()].ElementData;
|
|
||||||
}
|
|
||||||
FORCEINLINE ArrayType* operator->()
|
|
||||||
{
|
|
||||||
return &IteratedArray[BitArrayIt.GetIndex()].ElementData;
|
|
||||||
}
|
|
||||||
FORCEINLINE const ArrayType* operator->() const
|
|
||||||
{
|
|
||||||
return &IteratedArray[BitArrayIt.GetIndex()].ElementData;
|
|
||||||
}
|
|
||||||
FORCEINLINE bool operator==(const TSparseArray<ArrayType>::FBaseIterator& Other) const
|
|
||||||
{
|
|
||||||
return BitArrayIt == Other.BitArrayIt;
|
|
||||||
}
|
|
||||||
FORCEINLINE bool operator!=(const TSparseArray<ArrayType>::FBaseIterator& Other) const
|
|
||||||
{
|
|
||||||
return BitArrayIt != Other.BitArrayIt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE int32 GetIndex() const
|
/** inverse of the "bool" operator */
|
||||||
|
FORCEINLINE bool operator !() const
|
||||||
{
|
{
|
||||||
return BitArrayIt.GetIndex();
|
return !(bool)*this;
|
||||||
}
|
|
||||||
FORCEINLINE bool IsElementValid() const
|
|
||||||
{
|
|
||||||
return *BitArrayIt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCEINLINE ItElementType& operator*() const { return Array[GetIndex()]; }
|
||||||
|
FORCEINLINE ItElementType* operator->() const { return &Array[GetIndex()]; }
|
||||||
|
FORCEINLINE const FRelativeBitReference& GetRelativeBitReference() const { return BitArrayIt; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ArrayType& Array;
|
||||||
|
BitArrayItType BitArrayIt;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FORCEINLINE TSparseArray<ArrayType>::FBaseIterator begin()
|
|
||||||
|
/** Iterates over all allocated elements in a sparse array. */
|
||||||
|
class TIterator : public TBaseIterator<false>
|
||||||
{
|
{
|
||||||
return TSparseArray<ArrayType>::FBaseIterator(*this, TBitArray::FSetBitIterator(AllocationFlags, 0));
|
public:
|
||||||
}
|
TIterator(TSparseArray& InArray)
|
||||||
FORCEINLINE const TSparseArray<ArrayType>::FBaseIterator begin() const
|
: TBaseIterator<false>(InArray, TConstSetBitIterator<typename Allocator::BitArrayAllocator>(InArray.AllocationFlags))
|
||||||
{
|
{
|
||||||
return TSparseArray<ArrayType>::FBaseIterator(*this, TBitArray::FSetBitIterator(AllocationFlags, 0));
|
|
||||||
}
|
|
||||||
FORCEINLINE TSparseArray<ArrayType>::FBaseIterator end()
|
|
||||||
{
|
|
||||||
return TSparseArray<ArrayType>::FBaseIterator(*this, TBitArray::FSetBitIterator(AllocationFlags));
|
|
||||||
}
|
|
||||||
FORCEINLINE const TSparseArray<ArrayType>::FBaseIterator end() const
|
|
||||||
{
|
|
||||||
return TSparseArray<ArrayType>::FBaseIterator(*this, TBitArray::FSetBitIterator(AllocationFlags));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE FSparseArrayElement& operator[](uint32 Index)
|
TIterator(TSparseArray& InArray, const typename TBaseIterator<false>::BitArrayItType& InBitArrayIt)
|
||||||
|
: TBaseIterator<false>(InArray, InBitArrayIt)
|
||||||
{
|
{
|
||||||
return *(FSparseArrayElement*)&Data.at(Index).ElementData;
|
|
||||||
}
|
}
|
||||||
FORCEINLINE const FSparseArrayElement& operator[](uint32 Index) const
|
|
||||||
|
/** Safely removes the current element from the array. */
|
||||||
|
/*
|
||||||
|
void RemoveCurrent()
|
||||||
{
|
{
|
||||||
return *(const FSparseArrayElement*)&Data.at(Index).ElementData;
|
this->Array.RemoveAt(this->GetIndex());
|
||||||
}
|
}
|
||||||
FORCEINLINE int32 GetNumFreeIndices() const
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Iterates over all allocated elements in a const sparse array. */
|
||||||
|
class TConstIterator : public TBaseIterator<true>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TConstIterator(const TSparseArray& InArray)
|
||||||
|
: TBaseIterator<true>(InArray, TConstSetBitIterator<typename Allocator::BitArrayAllocator>(InArray.AllocationFlags))
|
||||||
{
|
{
|
||||||
return NumFreeIndices;
|
|
||||||
}
|
}
|
||||||
FORCEINLINE int32 GetFirstFreeIndex() const
|
|
||||||
|
TConstIterator(const TSparseArray& InArray, const typename TBaseIterator<true>::BitArrayItType& InBitArrayIt)
|
||||||
|
: TBaseIterator<true>(InArray, InBitArrayIt)
|
||||||
{
|
{
|
||||||
return FirstFreeIndex;
|
|
||||||
}
|
}
|
||||||
FORCEINLINE const TArray<FSparseArrayElement>& GetData() const
|
};
|
||||||
|
|
||||||
|
#if TSPARSEARRAY_RANGED_FOR_CHECKS // T(R) Milxnor: Check this
|
||||||
|
class TRangedForIterator : public TIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TRangedForIterator(TSparseArray& InArray, const typename TBaseIterator<false>::BitArrayItType& InBitArrayIt)
|
||||||
|
: TIterator(InArray, InBitArrayIt)
|
||||||
|
, InitialNum(InArray.Num())
|
||||||
{
|
{
|
||||||
return Data;
|
|
||||||
}
|
}
|
||||||
FSparseArrayElement& GetData(int32 Index)
|
|
||||||
|
private:
|
||||||
|
int32 InitialNum;
|
||||||
|
|
||||||
|
friend FORCEINLINE bool operator!=(const TRangedForIterator& Lhs, const TRangedForIterator& Rhs)
|
||||||
{
|
{
|
||||||
return *(FSparseArrayElement*)&Data.at(Index).ElementData;
|
// We only need to do the check in this operator, because no other operator will be
|
||||||
// return ((FSparseArrayElement*)Data.Data)[Index];
|
// called until after this one returns.
|
||||||
|
//
|
||||||
|
// Also, we should only need to check one side of this comparison - if the other iterator isn't
|
||||||
|
// even from the same array then the compiler has generated bad code.
|
||||||
|
ensureMsgf(Lhs.Array.Num() == Lhs.InitialNum, TEXT("Container has changed during ranged-for iteration!"));
|
||||||
|
return *(TIterator*)&Lhs != *(TIterator*)&Rhs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class TRangedForConstIterator : public TConstIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TRangedForConstIterator(const TSparseArray& InArray, const typename TBaseIterator<true>::BitArrayItType& InBitArrayIt)
|
||||||
|
: TConstIterator(InArray, InBitArrayIt)
|
||||||
|
, InitialNum(InArray.Num())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32 InitialNum;
|
||||||
|
|
||||||
|
friend FORCEINLINE bool operator!=(const TRangedForConstIterator& Lhs, const TRangedForConstIterator& Rhs)
|
||||||
|
{
|
||||||
|
// We only need to do the check in this operator, because no other operator will be
|
||||||
|
// called until after this one returns.
|
||||||
|
//
|
||||||
|
// Also, we should only need to check one side of this comparison - if the other iterator isn't
|
||||||
|
// even from the same array then the compiler has generated bad code.
|
||||||
|
ensureMsgf(Lhs.Array.Num() == Lhs.InitialNum, TEXT("Container has changed during ranged-for iteration!"));
|
||||||
|
return *(TIterator*)&Lhs != *(TIterator*)&Rhs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
using TRangedForIterator = TIterator;
|
||||||
|
using TRangedForConstIterator = TConstIterator;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ElementType& operator[](int32 Index)
|
||||||
|
{
|
||||||
|
// checkSlow(Index >= 0 && Index < Data.Num() && Index < AllocationFlags.Num());
|
||||||
|
//checkSlow(AllocationFlags[Index]); // Disabled to improve loading times -BZ
|
||||||
|
return *(ElementType*)&GetData(Index).ElementData;
|
||||||
|
}
|
||||||
|
const ElementType& operator[](int32 Index) const
|
||||||
|
{
|
||||||
|
// checkSlow(Index >= 0 && Index < Data.Num() && Index < AllocationFlags.Num());
|
||||||
|
//checkSlow(AllocationFlags[Index]); // Disabled to improve loading times -BZ
|
||||||
|
return *(ElementType*)&GetData(Index).ElementData;
|
||||||
|
}
|
||||||
|
|
||||||
|
FElementOrFreeListLink& GetData(int32 Index)
|
||||||
|
{
|
||||||
|
return ((FElementOrFreeListLink*)Data.GetData())[Index];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Accessor for the element or free list data. */
|
/** Accessor for the element or free list data. */
|
||||||
const FSparseArrayElement& GetData(int32 Index) const
|
const FElementOrFreeListLink& GetData(int32 Index) const
|
||||||
{
|
{
|
||||||
return *(const FSparseArrayElement*)&Data.at(Index).ElementData;
|
return ((FElementOrFreeListLink*)Data.GetData())[Index];
|
||||||
// return ((FSparseArrayElement*)Data.Data)[Index];
|
|
||||||
}
|
|
||||||
FORCEINLINE const TBitArray& GetAllocationFlags() const
|
|
||||||
{
|
|
||||||
return AllocationFlags;
|
|
||||||
}
|
|
||||||
FORCEINLINE bool IsIndexValid(int32 IndexToCheck) const
|
|
||||||
{
|
|
||||||
return AllocationFlags.IsSet(IndexToCheck);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveAt(int32 Index, int32 Count = 1)
|
FORCEINLINE friend TRangedForIterator begin(TSparseArray& Array) { return TRangedForIterator(Array, TConstSetBitIterator<typename Allocator::BitArrayAllocator>(Array.AllocationFlags)); }
|
||||||
{
|
FORCEINLINE friend TRangedForConstIterator begin(const TSparseArray& Array) { return TRangedForConstIterator(Array, TConstSetBitIterator<typename Allocator::BitArrayAllocator>(Array.AllocationFlags)); }
|
||||||
/* if (!TIsTriviallyDestructible<ElementType>::Value)
|
FORCEINLINE friend TRangedForIterator end(TSparseArray& Array) { return TRangedForIterator(Array, TConstSetBitIterator<typename Allocator::BitArrayAllocator>(Array.AllocationFlags, Array.AllocationFlags.Num())); }
|
||||||
{
|
FORCEINLINE friend TRangedForConstIterator end(const TSparseArray& Array) { return TRangedForConstIterator(Array, TConstSetBitIterator<typename Allocator::BitArrayAllocator>(Array.AllocationFlags, Array.AllocationFlags.Num())); }
|
||||||
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.Set(Index, false);
|
|
||||||
// AllocationFlags[Index] = false;
|
|
||||||
|
|
||||||
++Index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
FORCEINLINE bool RemoveAt(const int32 IndexToRemove)
|
|
||||||
{
|
|
||||||
LOG_INFO(LogDev, "IndexToRemove: {}", IndexToRemove);
|
|
||||||
LOG_INFO(LogDev, "AllocationFlags.IsSet(IndexToRemove): {}", AllocationFlags.IsSet(IndexToRemove));
|
|
||||||
LOG_INFO(LogDev, "Data.Num(): {}", Data.Num());
|
|
||||||
|
|
||||||
if (IndexToRemove >= 0 && IndexToRemove < Data.Num() && AllocationFlags.IsSet(IndexToRemove))
|
|
||||||
{
|
|
||||||
int32 PreviousFreeIndex = -1;
|
|
||||||
int32 NextFreeIndex = -1;
|
|
||||||
|
|
||||||
LOG_INFO(LogDev, "NumFreeIndices: {}", NumFreeIndices);
|
|
||||||
|
|
||||||
if (NumFreeIndices == 0)
|
|
||||||
{
|
|
||||||
FirstFreeIndex = IndexToRemove;
|
|
||||||
Data.at(IndexToRemove) = { -1, -1 };
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (auto It = AllocationFlags.begin(); It != AllocationFlags.end(); ++It)
|
|
||||||
{
|
|
||||||
if (!It)
|
|
||||||
{
|
|
||||||
if (It.GetIndex() < IndexToRemove)
|
|
||||||
{
|
|
||||||
Data.at(IndexToRemove).PrevFreeIndex = It.GetIndex();
|
|
||||||
}
|
|
||||||
else if (It.GetIndex() > IndexToRemove)
|
|
||||||
{
|
|
||||||
Data.at(IndexToRemove).NextFreeIndex = It.GetIndex();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AllocationFlags.Set(IndexToRemove, false);
|
|
||||||
NumFreeIndices++;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
@@ -16,7 +16,7 @@ struct FTimerUnifiedDelegate
|
|||||||
TFunction<void(void)> FuncCallback;
|
TFunction<void(void)> FuncCallback;
|
||||||
|
|
||||||
FTimerUnifiedDelegate() {};
|
FTimerUnifiedDelegate() {};
|
||||||
FTimerUnifiedDelegate(FTimerDelegate const& D) : FuncDelegate(D) {};
|
// FTimerUnifiedDelegate(FTimerDelegate const& D) : FuncDelegate(D) {}; // T(R)
|
||||||
};
|
};
|
||||||
|
|
||||||
class FTimerManager // : public FNoncopyable
|
class FTimerManager // : public FNoncopyable
|
||||||
@@ -27,6 +27,6 @@ public:
|
|||||||
static void (*InternalSetTimerOriginal)(__int64 TimerManager, FTimerHandle& InOutHandle, FTimerUnifiedDelegate&& InDelegate, float InRate, bool InbLoop, float InFirstDelay) =
|
static void (*InternalSetTimerOriginal)(__int64 TimerManager, FTimerHandle& InOutHandle, FTimerUnifiedDelegate&& InDelegate, float InRate, bool InbLoop, float InFirstDelay) =
|
||||||
decltype(InternalSetTimerOriginal)(Addresses::SetTimer);
|
decltype(InternalSetTimerOriginal)(Addresses::SetTimer);
|
||||||
|
|
||||||
InternalSetTimerOriginal(__int64(this), InOutHandle, FTimerUnifiedDelegate(InDelegate), InRate, InbLoop, InFirstDelay);
|
// InternalSetTimerOriginal(__int64(this), InOutHandle, FTimerUnifiedDelegate(InDelegate), InRate, InbLoop, InFirstDelay); // T(R)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -16,6 +16,93 @@ struct FMath : public FGenericPlatformMath
|
|||||||
return A * A;
|
return A * A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float SRand() // T(REP)
|
||||||
|
{
|
||||||
|
return rand();
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCEINLINE uint32 FloorLog2(uint32 Value)
|
||||||
|
{
|
||||||
|
/* // reference implementation
|
||||||
|
// 1500ms on test data
|
||||||
|
uint32 Bit = 32;
|
||||||
|
for (; Bit > 0;)
|
||||||
|
{
|
||||||
|
Bit--;
|
||||||
|
if (Value & (1<<Bit))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Bit;
|
||||||
|
*/
|
||||||
|
// same output as reference
|
||||||
|
|
||||||
|
// see http://codinggorilla.domemtech.com/?p=81 or http://en.wikipedia.org/wiki/Binary_logarithm but modified to return 0 for a input value of 0
|
||||||
|
// 686ms on test data
|
||||||
|
uint32 pos = 0;
|
||||||
|
if (Value >= 1 << 16) { Value >>= 16; pos += 16; }
|
||||||
|
if (Value >= 1 << 8) { Value >>= 8; pos += 8; }
|
||||||
|
if (Value >= 1 << 4) { Value >>= 4; pos += 4; }
|
||||||
|
if (Value >= 1 << 2) { Value >>= 2; pos += 2; }
|
||||||
|
if (Value >= 1 << 1) { pos += 1; }
|
||||||
|
return (Value == 0) ? 0 : pos;
|
||||||
|
|
||||||
|
// even faster would be method3 but it can introduce more cache misses and it would need to store the table somewhere
|
||||||
|
// 304ms in test data
|
||||||
|
/*int LogTable256[256];
|
||||||
|
|
||||||
|
void prep()
|
||||||
|
{
|
||||||
|
LogTable256[0] = LogTable256[1] = 0;
|
||||||
|
for (int i = 2; i < 256; i++)
|
||||||
|
{
|
||||||
|
LogTable256[i] = 1 + LogTable256[i / 2];
|
||||||
|
}
|
||||||
|
LogTable256[0] = -1; // if you want log(0) to return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
int _forceinline method3(uint32 v)
|
||||||
|
{
|
||||||
|
int r; // r will be lg(v)
|
||||||
|
uint32 tt; // temporaries
|
||||||
|
|
||||||
|
if ((tt = v >> 24) != 0)
|
||||||
|
{
|
||||||
|
r = (24 + LogTable256[tt]);
|
||||||
|
}
|
||||||
|
else if ((tt = v >> 16) != 0)
|
||||||
|
{
|
||||||
|
r = (16 + LogTable256[tt]);
|
||||||
|
}
|
||||||
|
else if ((tt = v >> 8 ) != 0)
|
||||||
|
{
|
||||||
|
r = (8 + LogTable256[tt]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = LogTable256[v];
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCEINLINE uint32 CountLeadingZeros(uint32 Value)
|
||||||
|
{
|
||||||
|
if (Value == 0) return 32;
|
||||||
|
return 31 - FloorLog2(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
static constexpr FORCEINLINE T DivideAndRoundUp(T Dividend, T Divisor)
|
||||||
|
{
|
||||||
|
return (Dividend + Divisor - 1) / Divisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCEINLINE int32 Rand() { return rand(); }
|
||||||
|
|
||||||
|
static FORCEINLINE float FRand() { return Rand() / (float)RAND_MAX; }
|
||||||
|
|
||||||
#define FASTASIN_HALF_PI (1.5707963050f)
|
#define FASTASIN_HALF_PI (1.5707963050f)
|
||||||
/**
|
/**
|
||||||
* Computes the ASin of a scalar value.
|
* Computes the ASin of a scalar value.
|
||||||
|
|||||||
@@ -26,6 +26,14 @@ struct TCallTraitsParamTypeHelper<T*, true>
|
|||||||
typedef const T* ConstParamType;
|
typedef const T* ConstParamType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T> struct TContainerTraitsBase
|
||||||
|
{
|
||||||
|
// This should be overridden by every container that supports emptying its contents via a move operation.
|
||||||
|
enum { MoveWillEmptyContainer = false };
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> struct TContainerTraits : public TContainerTraitsBase<T> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct TCallTraitsBase
|
struct TCallTraitsBase
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
|
|
||||||
#include "inc.h"
|
#include "inc.h"
|
||||||
|
|
||||||
|
enum EForceInit
|
||||||
|
{
|
||||||
|
ForceInit,
|
||||||
|
ForceInitToZero
|
||||||
|
};
|
||||||
|
|
||||||
struct FVector
|
struct FVector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -62,4 +68,10 @@ public:
|
|||||||
{
|
{
|
||||||
*this = *this - A;
|
*this = *this - A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit FORCEINLINE FVector(EForceInit)
|
||||||
|
: X(0.0f), Y(0.0f), Z(0.0f)
|
||||||
|
{
|
||||||
|
// DiagnosticCheckNaN();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
@@ -13,6 +13,19 @@ public:
|
|||||||
return ChunkedObjects ? ChunkedObjects->GetObjectByIndex(ObjectIndex) : UnchunkedObjects ? UnchunkedObjects->GetObjectByIndex(ObjectIndex) : nullptr;
|
return ChunkedObjects ? ChunkedObjects->GetObjectByIndex(ObjectIndex) : UnchunkedObjects ? UnchunkedObjects->GetObjectByIndex(ObjectIndex) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCEINLINE bool operator==(const FWeakObjectPtr& Other) const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(ObjectIndex == Other.ObjectIndex && ObjectSerialNumber == Other.ObjectSerialNumber)
|
||||||
|
// || (!IsValid() && !Other.IsValid())
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend uint32 GetTypeHash(const FWeakObjectPtr& WeakObjectPtr)
|
||||||
|
{
|
||||||
|
return uint32(WeakObjectPtr.ObjectIndex ^ WeakObjectPtr.ObjectSerialNumber);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const FWeakObjectPtr& other)
|
bool operator==(const FWeakObjectPtr& other)
|
||||||
{
|
{
|
||||||
return ObjectIndex == other.ObjectIndex && ObjectSerialNumber == other.ObjectSerialNumber;
|
return ObjectIndex == other.ObjectIndex && ObjectSerialNumber == other.ObjectSerialNumber;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "WeakObjectPtr.h"
|
#include "WeakObjectPtr.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
#include "PointerIsConvertibleFromTo.h"
|
||||||
|
|
||||||
template<class T = UObject, class TWeakObjectPtrBase = FWeakObjectPtr>
|
template<class T = UObject, class TWeakObjectPtrBase = FWeakObjectPtr>
|
||||||
struct TWeakObjectPtr;
|
struct TWeakObjectPtr;
|
||||||
@@ -14,8 +15,48 @@ struct TWeakObjectPtr : public TWeakObjectPtrBase
|
|||||||
return (T*)TWeakObjectPtrBase::Get();
|
return (T*)TWeakObjectPtrBase::Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
bool operator==(const TWeakObjectPtr& other)
|
bool operator==(const TWeakObjectPtr& other)
|
||||||
{
|
{
|
||||||
return TWeakObjectPtrBase::operator==(other);
|
return TWeakObjectPtrBase::operator==(other);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
TWeakObjectPtr() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename LhsT, typename RhsT, typename OtherTWeakObjectPtrBase>
|
||||||
|
FORCENOINLINE bool operator==(const TWeakObjectPtr<LhsT, OtherTWeakObjectPtrBase>& Lhs, const RhsT* Rhs)
|
||||||
|
{
|
||||||
|
// It's also possible that these static_asserts may fail for valid conversions because
|
||||||
|
// one or both of the types have only been forward-declared.
|
||||||
|
static_assert(TPointerIsConvertibleFromTo<RhsT, UObject>::Value, "TWeakObjectPtr can only be compared with UObject types");
|
||||||
|
static_assert(TPointerIsConvertibleFromTo<LhsT, RhsT>::Value || TPointerIsConvertibleFromTo<RhsT, LhsT>::Value, "Unable to compare TWeakObjectPtr with raw pointer - types are incompatible");
|
||||||
|
|
||||||
|
// NOTE: this constructs a TWeakObjectPtrBase, which has some amount of overhead, so this may not be an efficient operation
|
||||||
|
return (const OtherTWeakObjectPtrBase&)Lhs == OtherTWeakObjectPtrBase(Rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename LhsT, typename RhsT, typename OtherTWeakObjectPtrBase>
|
||||||
|
FORCENOINLINE bool operator==(const LhsT* Lhs, const TWeakObjectPtr<RhsT, OtherTWeakObjectPtrBase>& Rhs)
|
||||||
|
{
|
||||||
|
// It's also possible that these static_asserts may fail for valid conversions because
|
||||||
|
// one or both of the types have only been forward-declared.
|
||||||
|
static_assert(TPointerIsConvertibleFromTo<LhsT, UObject>::Value, "TWeakObjectPtr can only be compared with UObject types");
|
||||||
|
static_assert(TPointerIsConvertibleFromTo<LhsT, RhsT>::Value || TPointerIsConvertibleFromTo<RhsT, LhsT>::Value, "Unable to compare TWeakObjectPtr with raw pointer - types are incompatible");
|
||||||
|
|
||||||
|
// NOTE: this constructs a TWeakObjectPtrBase, which has some amount of overhead, so this may not be an efficient operation
|
||||||
|
return OtherTWeakObjectPtrBase(Lhs) == (const OtherTWeakObjectPtrBase&)Rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename LhsT, typename OtherTWeakObjectPtrBase>
|
||||||
|
FORCENOINLINE bool operator==(const TWeakObjectPtr<LhsT, OtherTWeakObjectPtrBase>& Lhs, TYPE_OF_NULLPTR)
|
||||||
|
{
|
||||||
|
return !Lhs.IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RhsT, typename OtherTWeakObjectPtrBase>
|
||||||
|
FORCENOINLINE bool operator==(TYPE_OF_NULLPTR, const TWeakObjectPtr<RhsT, OtherTWeakObjectPtrBase>& Rhs)
|
||||||
|
{
|
||||||
|
return !Rhs.IsValid();
|
||||||
|
}
|
||||||
@@ -6,17 +6,14 @@
|
|||||||
#include "Rotator.h"
|
#include "Rotator.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "GameInstance.h"
|
#include "GameInstance.h"
|
||||||
|
#include "WorldSettings.h"
|
||||||
|
#include "GameplayStatics.h"
|
||||||
|
|
||||||
struct FNetworkNotify
|
struct FNetworkNotify
|
||||||
{
|
{
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AWorldSettings : public AActor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FActorSpawnParameters
|
struct FActorSpawnParameters
|
||||||
{
|
{
|
||||||
FName Name = FName(0);
|
FName Name = FName(0);
|
||||||
@@ -228,6 +225,11 @@ public:
|
|||||||
return this->Get<class UNetDriver*>(NetDriverOffset);
|
return this->Get<class UNetDriver*>(NetDriverOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GetTimeSeconds() // T(REP)
|
||||||
|
{
|
||||||
|
return UGameplayStatics::GetTimeSeconds(this);
|
||||||
|
}
|
||||||
|
|
||||||
UGameInstance* GetOwningGameInstance()
|
UGameInstance* GetOwningGameInstance()
|
||||||
{
|
{
|
||||||
static auto OwningGameInstanceOffset = GetOffset("OwningGameInstance");
|
static auto OwningGameInstanceOffset = GetOffset("OwningGameInstance");
|
||||||
|
|||||||
35
Project Reboot 3.0/WorldSettings.h
Normal file
35
Project Reboot 3.0/WorldSettings.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Actor.h"
|
||||||
|
#include "NetConnection.h"
|
||||||
|
#include "Array.h"
|
||||||
|
|
||||||
|
struct FNetViewer
|
||||||
|
{
|
||||||
|
UNetConnection* Connection;
|
||||||
|
AActor* InViewer;
|
||||||
|
AActor* ViewTarget;
|
||||||
|
FVector ViewLocation;
|
||||||
|
FVector ViewDir;
|
||||||
|
|
||||||
|
FNetViewer()
|
||||||
|
: Connection(NULL)
|
||||||
|
, InViewer(NULL)
|
||||||
|
, ViewTarget(NULL)
|
||||||
|
, ViewLocation(ForceInit)
|
||||||
|
, ViewDir(ForceInit)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FNetViewer(UNetConnection* InConnection, float DeltaSeconds);
|
||||||
|
};
|
||||||
|
|
||||||
|
class AWorldSettings : public AActor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TArray<struct FNetViewer>& GetReplicationViewers()
|
||||||
|
{
|
||||||
|
static auto ReplicationViewersOffset = GetOffset("ReplicationViewers");
|
||||||
|
return Get<TArray<struct FNetViewer>>(ReplicationViewersOffset);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -553,6 +553,12 @@ void Addresses::Init()
|
|||||||
NavSystemCleanUpOriginal = decltype(NavSystemCleanUpOriginal)(Addresses::NavSystemCleanUp);
|
NavSystemCleanUpOriginal = decltype(NavSystemCleanUpOriginal)(Addresses::NavSystemCleanUp);
|
||||||
LoadPlaysetOriginal = decltype(LoadPlaysetOriginal)(Addresses::LoadPlayset);
|
LoadPlaysetOriginal = decltype(LoadPlaysetOriginal)(Addresses::LoadPlayset);
|
||||||
AFortGameModeAthena::SetZoneToIndexOriginal = decltype(AFortGameModeAthena::SetZoneToIndexOriginal)(Addresses::SetZoneToIndex);
|
AFortGameModeAthena::SetZoneToIndexOriginal = decltype(AFortGameModeAthena::SetZoneToIndexOriginal)(Addresses::SetZoneToIndex);
|
||||||
|
AActor::originalCallPreReplication = decltype(AActor::originalCallPreReplication)(Addresses::CallPreReplication);
|
||||||
|
APlayerController::originalSendClientAdjustment = decltype(APlayerController::originalSendClientAdjustment)(Addresses::SendClientAdjustment);
|
||||||
|
UActorChannel::originalReplicateActor = decltype(UActorChannel::originalReplicateActor)(Addresses::ReplicateActor);
|
||||||
|
UActorChannel::originalSetChannelActor = decltype(UActorChannel::originalSetChannelActor)(Addresses::SetChannelActor);
|
||||||
|
UNetConnection::originalCreateChannel = decltype(UNetConnection::originalCreateChannel)(Addresses::CreateChannel);
|
||||||
|
UNetConnection::originalCreateChannelByName = decltype(UNetConnection::originalCreateChannelByName)(Addresses::CreateChannel);
|
||||||
|
|
||||||
if (Engine_Version >= 421) ChunkedObjects = decltype(ChunkedObjects)(ObjectArray);
|
if (Engine_Version >= 421) ChunkedObjects = decltype(ChunkedObjects)(ObjectArray);
|
||||||
else UnchunkedObjects = decltype(UnchunkedObjects)(ObjectArray);
|
else UnchunkedObjects = decltype(UnchunkedObjects)(ObjectArray);
|
||||||
|
|||||||
@@ -110,11 +110,29 @@ static inline AFortAthenaMutator_Bots* SpawnBotMutator() //sets up all the class
|
|||||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode());
|
auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode());
|
||||||
|
|
||||||
|
auto MutatorBotsClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaMutator_Bots");
|
||||||
|
|
||||||
|
if (!MutatorBotsClass)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static auto BGAClass = FindObject<UClass>(L"/Script/Engine.BlueprintGeneratedClass");
|
static auto BGAClass = FindObject<UClass>(L"/Script/Engine.BlueprintGeneratedClass");
|
||||||
static auto PhoebeMutatorClass = LoadObject<UClass>(L"/Game/Athena/AI/Phoebe/BP_Phoebe_Mutator.BP_Phoebe_Mutator_C", BGAClass);
|
static auto PhoebeMutatorClass = LoadObject<UClass>(L"/Game/Athena/AI/Phoebe/BP_Phoebe_Mutator.BP_Phoebe_Mutator_C", BGAClass);
|
||||||
|
|
||||||
|
if (!PhoebeMutatorClass)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
auto BotMutator = GetWorld()->SpawnActor<AFortAthenaMutator_Bots>(PhoebeMutatorClass);
|
auto BotMutator = GetWorld()->SpawnActor<AFortAthenaMutator_Bots>(PhoebeMutatorClass);
|
||||||
|
|
||||||
|
if (!BotMutator)
|
||||||
|
{
|
||||||
|
LOG_WARN(LogAI, "Failed to spawn Bot Mutator!");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static auto CachedGameModeOffset = BotMutator->GetOffset("CachedGameMode");
|
static auto CachedGameModeOffset = BotMutator->GetOffset("CachedGameMode");
|
||||||
BotMutator->Get(CachedGameModeOffset) = GameMode;
|
BotMutator->Get(CachedGameModeOffset) = GameMode;
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,16 @@
|
|||||||
#include <format>
|
#include <format>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
T(REP): Todo replication
|
||||||
|
T(R): Todo random (every commented check, checkslow is automatically this)
|
||||||
|
T(1-5): 1, being most important, 5 being least important to fix.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
decltype(nullptr) typedef TYPE_OF_NULLPTR;
|
||||||
|
|
||||||
typedef unsigned short uint16;
|
typedef unsigned short uint16;
|
||||||
typedef unsigned char uint8;
|
typedef unsigned char uint8;
|
||||||
typedef char int8;
|
typedef char int8;
|
||||||
@@ -25,6 +35,8 @@ extern inline int Fortnite_CL = 0;
|
|||||||
|
|
||||||
// #define ABOVE_S20
|
// #define ABOVE_S20
|
||||||
|
|
||||||
|
#define INDEX_NONE -1
|
||||||
|
|
||||||
struct PlaceholderBitfield
|
struct PlaceholderBitfield
|
||||||
{
|
{
|
||||||
uint8_t First : 1;
|
uint8_t First : 1;
|
||||||
@@ -62,6 +74,15 @@ inline bool IsRestartingSupported()
|
|||||||
return Engine_Version >= 419 && Engine_Version < 424;
|
return Engine_Version >= 419 && Engine_Version < 424;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ENetRole
|
||||||
|
{
|
||||||
|
ROLE_None,
|
||||||
|
ROLE_SimulatedProxy,
|
||||||
|
ROLE_AutonomousProxy,
|
||||||
|
ROLE_Authority,
|
||||||
|
ROLE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
enum class AllocatorType
|
enum class AllocatorType
|
||||||
|
|||||||
@@ -80,8 +80,9 @@ static inline UEngine* GetEngine()
|
|||||||
return Engine;
|
return Engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline class UWorld* GetWorld()
|
namespace {
|
||||||
{
|
static inline class UWorld* GetWorld()
|
||||||
|
{
|
||||||
static UObject* Engine = GetEngine();
|
static UObject* Engine = GetEngine();
|
||||||
static auto GameViewportOffset = Engine->GetOffset("GameViewport");
|
static auto GameViewportOffset = Engine->GetOffset("GameViewport");
|
||||||
auto GameViewport = Engine->Get<UObject*>(GameViewportOffset);
|
auto GameViewport = Engine->Get<UObject*>(GameViewportOffset);
|
||||||
@@ -89,6 +90,7 @@ static inline class UWorld* GetWorld()
|
|||||||
static auto WorldOffset = GameViewport->GetOffset("World");
|
static auto WorldOffset = GameViewport->GetOffset("World");
|
||||||
|
|
||||||
return GameViewport->Get<class UWorld*>(WorldOffset);
|
return GameViewport->Get<class UWorld*>(WorldOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TArray<UObject*>& GetLocalPlayers()
|
static TArray<UObject*>& GetLocalPlayers()
|
||||||
@@ -406,7 +408,8 @@ namespace MemberOffsets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline float GetMaxTickRateHook() { return 30.f; }
|
inline float ServerTickRate = 30.f;
|
||||||
|
static inline float GetMaxTickRateHook() { return ServerTickRate; }
|
||||||
|
|
||||||
#define VALIDATEOFFSET(offset) if (!offset) LOG_WARN(LogDev, "[{}] Invalid offset", __FUNCTIONNAME__);
|
#define VALIDATEOFFSET(offset) if (!offset) LOG_WARN(LogDev, "[{}] Invalid offset", __FUNCTIONNAME__);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user