mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
too much stuff
fix s3, fix health + backpack bug on 1.11, change replciation, fix 7.20 & 12.61, fix backpack on >S9, probably some other stuff i forgot
This commit is contained in:
@@ -126,6 +126,28 @@ void AActor::ForceNetUpdate()
|
||||
this->ProcessEvent(ForceNetUpdateFn);
|
||||
}
|
||||
|
||||
bool AActor::IsNetStartupActor()
|
||||
{
|
||||
return IsNetStartup(); // The implementation on this function depends on the version.
|
||||
}
|
||||
|
||||
bool AActor::IsPendingKillPending()
|
||||
{
|
||||
return IsActorBeingDestroyed() || !IsValidChecked(this);
|
||||
}
|
||||
|
||||
float& AActor::GetNetUpdateFrequency()
|
||||
{
|
||||
static auto NetUpdateFrequencyOffset = GetOffset("NetUpdateFrequency");
|
||||
return Get<float>(NetUpdateFrequencyOffset);
|
||||
}
|
||||
|
||||
float& AActor::GetMinNetUpdateFrequency()
|
||||
{
|
||||
static auto MinNetUpdateFrequencyOffset = GetOffset("MinNetUpdateFrequency");
|
||||
return Get<float>(MinNetUpdateFrequencyOffset);
|
||||
}
|
||||
|
||||
bool AActor::IsAlwaysRelevant()
|
||||
{
|
||||
static auto bAlwaysRelevantOffset = GetOffset("bAlwaysRelevant");
|
||||
|
||||
@@ -25,6 +25,10 @@ public:
|
||||
void SetCanBeDamaged(bool NewValue);
|
||||
void SetOwner(AActor* Owner);
|
||||
void ForceNetUpdate();
|
||||
bool IsNetStartupActor();
|
||||
bool IsPendingKillPending();
|
||||
float& GetNetUpdateFrequency();
|
||||
float& GetMinNetUpdateFrequency();
|
||||
|
||||
static class UClass* StaticClass();
|
||||
};
|
||||
@@ -2,6 +2,20 @@
|
||||
|
||||
#include "ContainerAllocationPolicies.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 NumBitsPerDWORDLogTwo ((int32)5)
|
||||
|
||||
class TBitArray
|
||||
{
|
||||
private:
|
||||
@@ -10,8 +24,308 @@ private:
|
||||
template <typename SetType>
|
||||
friend class TSet;
|
||||
|
||||
private:
|
||||
public:
|
||||
TInlineAllocator<4>::ForElementType<unsigned int> Data;
|
||||
int NumBits;
|
||||
int MaxBits;
|
||||
|
||||
struct FRelativeBitReference
|
||||
{
|
||||
public:
|
||||
FORCEINLINE explicit FRelativeBitReference(int32 BitIndex)
|
||||
: DWORDIndex(BitIndex >> NumBitsPerDWORDLogTwo)
|
||||
, Mask(1 << (BitIndex & ((NumBitsPerDWORD)-1)))
|
||||
{
|
||||
}
|
||||
|
||||
int32 DWORDIndex;
|
||||
uint32 Mask;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
, IteratedArray(const_cast<TBitArray&>(ToIterate))
|
||||
, UnvisitedBitMask((~0U) << (StartIndex & (NumBitsPerDWORD - 1)))
|
||||
, CurrentBitIndex(StartIndex)
|
||||
, BaseBitIndex(StartIndex & ~(NumBitsPerDWORD - 1))
|
||||
{
|
||||
if (StartIndex != IteratedArray.NumBits)
|
||||
{
|
||||
FindNextSetBit();
|
||||
}
|
||||
}
|
||||
FORCEINLINE FSetBitIterator(const TBitArray& ToIterate)
|
||||
: FRelativeBitReference(ToIterate.NumBits)
|
||||
, IteratedArray(const_cast<TBitArray&>(ToIterate))
|
||||
, UnvisitedBitMask(0)
|
||||
, CurrentBitIndex(ToIterate.NumBits)
|
||||
, BaseBitIndex(ToIterate.NumBits)
|
||||
{
|
||||
}
|
||||
|
||||
FORCEINLINE FSetBitIterator& operator++()
|
||||
{
|
||||
UnvisitedBitMask &= ~this->Mask;
|
||||
|
||||
FindNextSetBit();
|
||||
|
||||
return *this;
|
||||
}
|
||||
FORCEINLINE bool operator*() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator==(const FSetBitIterator& Other) const
|
||||
{
|
||||
return CurrentBitIndex == Other.CurrentBitIndex;
|
||||
}
|
||||
FORCEINLINE bool operator!=(const FSetBitIterator& Other) const
|
||||
{
|
||||
return CurrentBitIndex </*=*/ Other.CurrentBitIndex;
|
||||
}
|
||||
|
||||
FORCEINLINE explicit operator bool() const
|
||||
{
|
||||
return CurrentBitIndex < IteratedArray.NumBits;
|
||||
}
|
||||
|
||||
FORCEINLINE int32 GetIndex() const
|
||||
{
|
||||
return CurrentBitIndex;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void FindNextSetBit()
|
||||
{
|
||||
//InlineData is the first 16-bytes of TBitArray
|
||||
const uint32* ArrayData = (IteratedArray.Data.SecondaryData ? IteratedArray.Data.SecondaryData : (uint32*)&IteratedArray.Data.InlineData);
|
||||
|
||||
const int32 ArrayNum = IteratedArray.NumBits;
|
||||
const int32 LastDWORDIndex = (ArrayNum - 1) / NumBitsPerDWORD;
|
||||
|
||||
uint32 RemainingBitMask = ArrayData[this->DWORDIndex] & UnvisitedBitMask;
|
||||
while (!RemainingBitMask)
|
||||
{
|
||||
++this->DWORDIndex;
|
||||
BaseBitIndex += NumBitsPerDWORD;
|
||||
|
||||
if (this->DWORDIndex > LastDWORDIndex)
|
||||
{
|
||||
CurrentBitIndex = ArrayNum;
|
||||
return;
|
||||
}
|
||||
|
||||
RemainingBitMask = ArrayData[this->DWORDIndex];
|
||||
UnvisitedBitMask = ~0;
|
||||
}
|
||||
|
||||
const uint32 NewRemainingBitMask = RemainingBitMask & (RemainingBitMask - 1);
|
||||
|
||||
this->Mask = NewRemainingBitMask ^ RemainingBitMask;
|
||||
|
||||
CurrentBitIndex = BaseBitIndex + NumBitsPerDWORD - 1 - CountLeadingZeros(this->Mask);
|
||||
|
||||
if (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);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -25,5 +25,47 @@ public:
|
||||
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)
|
||||
{
|
||||
return *(ElementType*)(&InlineData[Index]);
|
||||
}
|
||||
FORCEINLINE const ElementType& operator[](int32 Index) const
|
||||
{
|
||||
return *(ElementType*)(&InlineData[Index]);
|
||||
}
|
||||
|
||||
FORCEINLINE void operator=(void* InElements)
|
||||
{
|
||||
SecondaryData = InElements;
|
||||
}
|
||||
|
||||
FORCEINLINE ElementType& GetInlineElement(int32 Index)
|
||||
{
|
||||
return *(ElementType*)(&InlineData[Index]);
|
||||
}
|
||||
FORCEINLINE const ElementType& GetInlineElement(int32 Index) const
|
||||
{
|
||||
return *(ElementType*)(&InlineData[Index]);
|
||||
}
|
||||
FORCEINLINE ElementType& GetSecondaryElement(int32 Index)
|
||||
{
|
||||
return SecondaryData[Index];
|
||||
}
|
||||
FORCEINLINE const ElementType& GetSecondaryElement(int32 Index) const
|
||||
{
|
||||
return SecondaryData[Index];
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -283,11 +283,13 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
||||
else
|
||||
{
|
||||
if (Fortnite_Version >= 4)
|
||||
{
|
||||
SetPlaylist(PlaylistToUse, true);
|
||||
|
||||
auto CurrentPlaylist = GameState->GetCurrentPlaylist();
|
||||
LOG_INFO(LogDev, "Set playlist to {}!", CurrentPlaylist->IsValidLowLevel() ? CurrentPlaylist->GetFullName() : "Invalid");
|
||||
}
|
||||
}
|
||||
|
||||
// if (false)
|
||||
{
|
||||
@@ -424,15 +426,17 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
||||
}
|
||||
}
|
||||
|
||||
auto PlaylistToUse = GetPlaylistToUse();
|
||||
static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false);
|
||||
|
||||
if (PlaylistToUse)
|
||||
auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist();
|
||||
|
||||
if (CurrentPlaylist)
|
||||
{
|
||||
static auto AdditionalLevelsOffset = PlaylistToUse->GetOffset("AdditionalLevels", false);
|
||||
static auto AdditionalLevelsOffset = CurrentPlaylist->GetOffset("AdditionalLevels", false);
|
||||
|
||||
if (AdditionalLevelsOffset != -1)
|
||||
{
|
||||
auto& AdditionalLevels = PlaylistToUse->Get<TArray<TSoftObjectPtr<UClass>>>(AdditionalLevelsOffset);
|
||||
auto& AdditionalLevels = CurrentPlaylist->Get<TArray<TSoftObjectPtr<UClass>>>(AdditionalLevelsOffset);
|
||||
|
||||
LOG_INFO(LogPlaylist, "Loading {} playlist levels.", AdditionalLevels.Num());
|
||||
|
||||
@@ -525,6 +529,10 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
||||
float TimeSeconds = UGameplayStatics::GetTimeSeconds(GetWorld());
|
||||
|
||||
LOG_INFO(LogDev, "Initializing!");
|
||||
|
||||
if (std::floor(Fortnite_Version) == 3)
|
||||
SetPlaylist(GetPlaylistToUse(), true);
|
||||
|
||||
LOG_INFO(LogDev, "GameMode 0x{:x}", __int64(GameMode));
|
||||
|
||||
GameState->Get<float>("WarmupCountdownEndTime") = TimeSeconds + Duration;
|
||||
@@ -539,26 +547,6 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
||||
|
||||
GameSession->Get<int>(MaxPlayersOffset) = 100;
|
||||
|
||||
/*
|
||||
auto AllMegaStormManagers = UGameplayStatics::GetAllActorsOfClass(GetWorld(), GameMode->Get<UClass*>("MegaStormManagerClass"));
|
||||
|
||||
LOG_INFO(LogDev, "AllMegaStormManagers.Num() {}", AllMegaStormManagers.Num());
|
||||
|
||||
if (AllMegaStormManagers.Num())
|
||||
{
|
||||
auto MegaStormManager = (AMegaStormManager*)AllMegaStormManagers.at(0); // GameMode->Get<AMegaStormManager*>(MegaStormManagerOffset);
|
||||
|
||||
LOG_INFO(LogDev, "MegaStormManager {}", __int64(MegaStormManager));
|
||||
|
||||
if (MegaStormManager)
|
||||
{
|
||||
LOG_INFO(LogDev, "MegaStormManager->GetMegaStormCircles().Num() {}", MegaStormManager->GetMegaStormCircles().Num());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// GameState->Get<bool>("bGameModeWillSkipAircraft") = Globals::bGoingToPlayEvent && Fortnite_Version == 17.30;
|
||||
|
||||
// if (Engine_Version < 424)
|
||||
GameState->OnRep_CurrentPlaylistInfo(); // ?
|
||||
|
||||
@@ -807,7 +795,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
||||
Parts[(int)EFortCustomPartType::Head] = headPart;
|
||||
Parts[(int)EFortCustomPartType::Body] = bodyPart;
|
||||
|
||||
if (Fortnite_Version > 2.5)
|
||||
// if (Fortnite_Version > 2.5)
|
||||
Parts[(int)EFortCustomPartType::Backpack] = backpackPart;
|
||||
|
||||
static auto OnRep_CharacterPartsFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerState.OnRep_CharacterParts");
|
||||
@@ -865,16 +853,9 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
||||
{
|
||||
UClass* AbilityClass = GameplayAbilities->At(i);
|
||||
|
||||
// LOG_INFO(LogDev, "AbilityClass {}", __int64(AbilityClass));
|
||||
|
||||
if (!AbilityClass)
|
||||
continue;
|
||||
|
||||
// LOG_INFO(LogDev, "AbilityClass Name {}", AbilityClass->GetFullName());
|
||||
|
||||
// LOG_INFO(LogDev, "DefaultAbility {}", __int64(DefaultAbility));
|
||||
// LOG_INFO(LogDev, "DefaultAbility Name {}", DefaultAbility->GetFullName());
|
||||
|
||||
PlayerStateAthena->GetAbilitySystemComponent()->GiveAbilityEasy(AbilityClass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
||||
|
||||
if (LoadedAmmo == -1)
|
||||
{
|
||||
if (auto WeaponDef = Cast<UFortWeaponItemDefinition>(ItemDefinition))
|
||||
if (auto WeaponDef = Cast<UFortWeaponItemDefinition>(ItemDefinition)) // bPreventDefaultPreload ?
|
||||
LoadedAmmo = WeaponDef->GetClipSize();
|
||||
else
|
||||
LoadedAmmo = 0;
|
||||
|
||||
@@ -229,6 +229,8 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
|
||||
auto GameFeatureData = Object;
|
||||
static auto DefaultLootTableDataOffset = GameFeatureData->GetOffset("DefaultLootTableData");
|
||||
|
||||
if (DefaultLootTableDataOffset != -1)
|
||||
{
|
||||
auto DefaultLootTableData = GameFeatureData->GetPtr<FFortGameFeatureLootTableData>(DefaultLootTableDataOffset);
|
||||
|
||||
auto LootTierDataTableStr = DefaultLootTableData->LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||
@@ -356,6 +358,7 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < LTDTables.size(); i++)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController
|
||||
if (Engine_Version <= 420)
|
||||
{
|
||||
static auto OverriddenBackpackSizeOffset = PlayerController->GetOffset("OverriddenBackpackSize");
|
||||
LOG_INFO(LogDev, "PlayerController->Get<int>(OverriddenBackpackSizeOffset): {}", PlayerController->Get<int>(OverriddenBackpackSizeOffset));
|
||||
// LOG_INFO(LogDev, "PlayerController->Get<int>(OverriddenBackpackSizeOffset): {}", PlayerController->Get<int>(OverriddenBackpackSizeOffset));
|
||||
// PlayerController->Get<int>(OverriddenBackpackSizeOffset) = 5;
|
||||
// PlayerController->ForceNetUpdate();
|
||||
}
|
||||
@@ -220,7 +220,7 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
||||
auto Vehicle = ReceivingActor;
|
||||
ServerAttemptInteractOriginal(Context, Stack, Ret);
|
||||
|
||||
return;
|
||||
// return;
|
||||
|
||||
auto Pawn = (AFortPlayerPawn*)PlayerController->GetMyFortPawn();
|
||||
|
||||
@@ -287,19 +287,6 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
||||
|
||||
return;
|
||||
}
|
||||
/*
|
||||
else if (ReceivingActor->IsA(FortAthenaSupplyDropClass))
|
||||
{
|
||||
auto LootTierGroup = ReceivingActor->IsA(LlamaClass) ? UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaLlama") : UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaSupplyDrop"); // SupplyDrop->GetLootTierGroupOverride();
|
||||
|
||||
auto LootDrops = PickLootDrops(LootTierGroup);
|
||||
|
||||
for (auto& LootDrop : LootDrops)
|
||||
{
|
||||
AFortPickup::SpawnPickup(LootDrop.ItemDefinition, LocationToSpawnLoot, LootDrop.Count, EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource::SupplyDrop);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return ServerAttemptInteractOriginal(Context, Stack, Ret);
|
||||
}
|
||||
|
||||
@@ -10,12 +10,29 @@
|
||||
|
||||
struct FFortAthenaLoadout
|
||||
{
|
||||
static UStruct* GetStruct()
|
||||
{
|
||||
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.FortAthenaLoadout");
|
||||
return Struct;
|
||||
}
|
||||
|
||||
static int GetStructSize()
|
||||
{
|
||||
return GetStruct()->GetPropertiesSize();
|
||||
}
|
||||
|
||||
UObject*& GetCharacter()
|
||||
{
|
||||
static auto CharacterOffset = FindOffsetStruct("/Script/FortniteGame.FortAthenaLoadout", "Character");
|
||||
return *(UObject**)(__int64(this) + CharacterOffset);
|
||||
}
|
||||
|
||||
UObject*& GetBackpack()
|
||||
{
|
||||
static auto BackpackOffset = FindOffsetStruct("/Script/FortniteGame.FortAthenaLoadout", "Backpack");
|
||||
return *(UObject**)(__int64(this) + BackpackOffset);
|
||||
}
|
||||
|
||||
UObject*& GetPickaxe()
|
||||
{
|
||||
static auto PickaxeOffset = FindOffsetStruct("/Script/FortniteGame.FortAthenaLoadout", "Pickaxe");
|
||||
|
||||
@@ -72,12 +72,19 @@ void AFortPlayerControllerAthena::ServerAcknowledgePossessionHook(APlayerControl
|
||||
auto PawnAsFort = Cast<AFortPlayerPawn>(Pawn);
|
||||
auto PlayerStateAsFort = Cast<AFortPlayerState>(Pawn->GetPlayerState());
|
||||
|
||||
if (Globals::bNoMCP)
|
||||
return;
|
||||
|
||||
if (!PawnAsFort)
|
||||
return;
|
||||
|
||||
if (Globals::bNoMCP)
|
||||
{
|
||||
static auto CustomCharacterPartClass = FindObject<UClass>("/Script/FortniteGame.CustomCharacterPart");
|
||||
static auto backpackPart = LoadObject("/Game/Characters/CharacterParts/Backpacks/NoBackpack.NoBackpack", CustomCharacterPartClass);
|
||||
|
||||
// PawnAsFort->ServerChoosePart(EFortCustomPartType::Backpack, backpackPart);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static auto UpdatePlayerCustomCharacterPartsVisualizationFn = FindObject<UFunction>("/Script/FortniteGame.FortKismetLibrary.UpdatePlayerCustomCharacterPartsVisualization");
|
||||
|
||||
if (!UpdatePlayerCustomCharacterPartsVisualizationFn)
|
||||
@@ -85,8 +92,41 @@ void AFortPlayerControllerAthena::ServerAcknowledgePossessionHook(APlayerControl
|
||||
auto CosmeticLoadout = ControllerAsFort->GetCosmeticLoadout();
|
||||
|
||||
if (CosmeticLoadout)
|
||||
{
|
||||
/* static auto Pawn_CosmeticLoadoutOffset = PawnAsFort->GetOffset("CosmeticLoadout");
|
||||
|
||||
if (Pawn_CosmeticLoadoutOffset != -1)
|
||||
{
|
||||
CopyStruct(PawnAsFort->GetPtr<__int64>(Pawn_CosmeticLoadoutOffset), CosmeticLoadout, FFortAthenaLoadout::GetStructSize());
|
||||
} */
|
||||
|
||||
ApplyCID(PawnAsFort, CosmeticLoadout->GetCharacter());
|
||||
|
||||
auto Backpack = CosmeticLoadout->GetBackpack();
|
||||
|
||||
if (Backpack)
|
||||
{
|
||||
static auto CharacterPartsOffset = Backpack->GetOffset("CharacterParts");
|
||||
|
||||
if (CharacterPartsOffset != -1)
|
||||
{
|
||||
auto& BackpackCharacterParts = Backpack->Get<TArray<UObject*>>(CharacterPartsOffset);
|
||||
|
||||
for (int i = 0; i < BackpackCharacterParts.Num(); i++)
|
||||
{
|
||||
auto BackpackCharacterPart = BackpackCharacterParts.at(i);
|
||||
|
||||
if (!BackpackCharacterPart)
|
||||
continue;
|
||||
|
||||
PawnAsFort->ServerChoosePart(EFortCustomPartType::Backpack, BackpackCharacterPart);
|
||||
}
|
||||
|
||||
// UFortKismetLibrary::ApplyCharacterCosmetics(GetWorld(), BackpackCharacterParts, PlayerStateAsFort, &aa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID)
|
||||
{
|
||||
auto& SpecializationSoft = Specializations.at(i);
|
||||
|
||||
auto Specialization = SpecializationSoft.Get();
|
||||
static auto FortHeroSpecializationClass = FindObject<UClass>("/Script/FortniteGame.FortHeroSpecialization");
|
||||
auto Specialization = SpecializationSoft.Get(FortHeroSpecializationClass, true);
|
||||
|
||||
if (Specialization)
|
||||
{
|
||||
@@ -40,7 +41,8 @@ static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID)
|
||||
for (int z = 0; z < CharacterParts.Num(); z++)
|
||||
{
|
||||
auto& CharacterPartSoft = CharacterParts.at(z);
|
||||
auto CharacterPart = CharacterPartSoft.Get();
|
||||
static auto CustomCharacterPartClass = FindObject<UClass>("/Script/FortniteGame.CustomCharacterPart");
|
||||
auto CharacterPart = CharacterPartSoft.Get(CustomCharacterPartClass, true);
|
||||
|
||||
CharacterPartsaa.Add(CharacterPart);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ void AFortPlayerPawn::ServerChoosePart(EFortCustomPartType Part, UObject* Chosen
|
||||
this->ProcessEvent(fn, &AFortPlayerPawn_ServerChoosePart_Params);
|
||||
}
|
||||
|
||||
void AFortPlayerPawn::ForceLaunchPlayerZiplinine() // Thanks android
|
||||
void AFortPlayerPawn::ForceLaunchPlayerZipline() // Thanks android
|
||||
{
|
||||
float ZiplineJumpDampening = -0.5f;
|
||||
float ZiplineJumpStrength = 1500.f;
|
||||
@@ -70,7 +70,7 @@ void AFortPlayerPawn::ServerSendZiplineStateHook(AFortPlayerPawn* Pawn, FZipline
|
||||
{
|
||||
if ((*(bool*)(__int64(PawnZiplineState) + bJumpedOffset)))
|
||||
{
|
||||
Pawn->ForceLaunchPlayerZiplinine();
|
||||
Pawn->ForceLaunchPlayerZipline();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class AFortPlayerPawn : public AFortPawn
|
||||
{
|
||||
public:
|
||||
void ServerChoosePart(EFortCustomPartType Part, class UObject* ChosenCharacterPart);
|
||||
void ForceLaunchPlayerZiplinine(); // Thanks android
|
||||
void ForceLaunchPlayerZipline(); // Thanks android
|
||||
|
||||
static void ServerSendZiplineStateHook(AFortPlayerPawn* Pawn, FZiplinePawnState InZiplineState);
|
||||
static void ServerHandlePickupHook(AFortPlayerPawn* Pawn, AFortPickup* Pickup, float InFlyTime, FVector InStartDirection, bool bPlayPickupSound);
|
||||
|
||||
25
Project Reboot 3.0/Level.cpp
Normal file
25
Project Reboot 3.0/Level.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "Level.h"
|
||||
|
||||
UWorld*& ULevel::GetOwningWorld()
|
||||
{
|
||||
static auto OwningWorldOffset = GetOffset("OwningWorld");
|
||||
return Get<UWorld*>(OwningWorldOffset);
|
||||
}
|
||||
|
||||
bool ULevel::HasVisibilityChangeRequestPending()
|
||||
{
|
||||
// I believe implementation on this changes depending on the version
|
||||
|
||||
auto OwningWorld = GetOwningWorld();
|
||||
|
||||
if (!OwningWorld)
|
||||
return false;
|
||||
|
||||
static auto CurrentLevelPendingVisibilityOffset = OwningWorld->GetOffset("CurrentLevelPendingVisibility");
|
||||
auto CurrentLevelPendingVisibility = OwningWorld->Get<ULevel*>(CurrentLevelPendingVisibilityOffset);
|
||||
|
||||
static auto CurrentLevelPendingInvisibilityOffset= OwningWorld->GetOffset("CurrentLevelPendingInvisibility");
|
||||
auto CurrentLevelPendingInvisibility = OwningWorld->Get<ULevel*>(CurrentLevelPendingInvisibilityOffset);
|
||||
|
||||
return this == CurrentLevelPendingVisibility || this == CurrentLevelPendingInvisibility;
|
||||
}
|
||||
10
Project Reboot 3.0/Level.h
Normal file
10
Project Reboot 3.0/Level.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "World.h"
|
||||
|
||||
class ULevel : public UObject
|
||||
{
|
||||
public:
|
||||
UWorld*& GetOwningWorld();
|
||||
bool HasVisibilityChangeRequestPending();
|
||||
};
|
||||
@@ -5,6 +5,20 @@
|
||||
#include "NetConnection.h"
|
||||
#include "FortPlayerControllerAthena.h"
|
||||
#include "GameplayStatics.h"
|
||||
#include "KismetMathLibrary.h"
|
||||
#include <random>
|
||||
|
||||
FNetworkObjectList& UNetDriver::GetNetworkObjectList()
|
||||
{
|
||||
return *(*(TSharedPtr<FNetworkObjectList>*)(__int64(this) + 0x490));
|
||||
}
|
||||
|
||||
void UNetDriver::RemoveNetworkActor(AActor* Actor)
|
||||
{
|
||||
GetNetworkObjectList().Remove(Actor);
|
||||
|
||||
// RenamedStartupActors.Remove(Actor->GetFName());
|
||||
}
|
||||
|
||||
void UNetDriver::TickFlushHook(UNetDriver* NetDriver)
|
||||
{
|
||||
@@ -34,7 +48,7 @@ int32 ServerReplicateActors_PrepConnections(UNetDriver* NetDriver)
|
||||
for (int32 ConnIdx = 0; ConnIdx < ClientConnections.Num(); ConnIdx++)
|
||||
{
|
||||
UNetConnection* Connection = ClientConnections.at(ConnIdx);
|
||||
// check(Connection);
|
||||
if (!Connection) continue;
|
||||
// check(Connection->State == USOCK_Pending || Connection->State == USOCK_Open || Connection->State == USOCK_Closed);
|
||||
// checkSlow(Connection->GetUChildConnection() == NULL);
|
||||
|
||||
@@ -42,13 +56,8 @@ int32 ServerReplicateActors_PrepConnections(UNetDriver* NetDriver)
|
||||
|
||||
if (OwningActor != NULL) // && /* Connection->State == USOCK_Open && */ (Connection->Driver->Time - Connection->LastReceiveTime < 1.5f))
|
||||
{
|
||||
// check(World == OwningActor->GetWorld());
|
||||
|
||||
bFoundReadyConnection = true;
|
||||
|
||||
// the view target is what the player controller is looking at OR the owning actor itself when using beacons
|
||||
// Connection->GetViewTarget() = Connection->GetPlayerController() ? Connection->GetPlayerController()->GetViewTarget() : OwningActor;
|
||||
|
||||
AActor* DesiredViewTarget = OwningActor;
|
||||
|
||||
if (Connection->GetPlayerController())
|
||||
@@ -90,42 +99,61 @@ enum class ENetDormancy : uint8_t
|
||||
ENetDormancy_MAX = 6
|
||||
};
|
||||
|
||||
struct FNetworkObjectInfo
|
||||
FORCEINLINE float FRand()
|
||||
{
|
||||
AActor* Actor;
|
||||
/* TWeakObjectPtr<AActor> WeakActor;
|
||||
double NextUpdateTime;
|
||||
double LastNetReplicateTime;
|
||||
float OptimalNetUpdateDelta;
|
||||
float LastNetUpdateTime;
|
||||
uint32 bPendingNetUpdate : 1;
|
||||
uint32 bForceRelevantNextUpdate : 1;
|
||||
TSet<TWeakObjectPtr<UNetConnection>> DormantConnections;
|
||||
TSet<TWeakObjectPtr<UNetConnection>> RecentlyDormantConnections; */
|
||||
};
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_real_distribution<> dis(0, 1);
|
||||
float random_number = dis(gen);
|
||||
|
||||
static void ServerReplicateActors_BuildConsiderList(UNetDriver* NetDriver, std::vector<FNetworkObjectInfo*>& OutConsiderList)
|
||||
return random_number;
|
||||
}
|
||||
|
||||
#define USEOBJECTLIST
|
||||
|
||||
void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList)
|
||||
{
|
||||
std::vector<AActor*> ActorsToRemove;
|
||||
|
||||
#ifdef USEOBJECTLIST
|
||||
auto& ActiveObjects = GetNetworkObjectList().ActiveNetworkObjects;
|
||||
#else
|
||||
TArray<AActor*> Actors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass());
|
||||
#endif
|
||||
|
||||
/* auto& ActiveObjects = GetNetworkObjectList(NetDriver).ActiveNetworkObjects;
|
||||
auto World = GetWorld();
|
||||
|
||||
for (int i = 0; i < ActiveObjects.Num(); i++)
|
||||
#ifdef USEOBJECTLIST
|
||||
// for (int i = 0; i < ActiveObjects.Elements.Num(); i++)
|
||||
for (const TSharedPtr<FNetworkObjectInfo>& ActorInfo : ActiveObjects)
|
||||
{
|
||||
auto ActorInfo = ActiveObjects.GetElements().GetData()[i].ElementData.Value.Get();
|
||||
auto Actor = ActorInfo->Actor; */
|
||||
// auto& ActorInfo = ActiveObjects.Elements.Data.at(i).ElementData.Value;
|
||||
|
||||
if (!ActorInfo->bPendingNetUpdate && UGameplayStatics::GetTimeSeconds(GetWorld()) <= ActorInfo->NextUpdateTime)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if (IsBadReadPtr(ActorInfo, 8))
|
||||
// continue;
|
||||
|
||||
auto Actor = ActorInfo->Actor;
|
||||
|
||||
#else
|
||||
|
||||
for (int i = 0; i < Actors.Num(); i++)
|
||||
{
|
||||
auto Actor = Actors.at(i);
|
||||
|
||||
#endif
|
||||
|
||||
if (!Actor)
|
||||
continue;
|
||||
|
||||
// if (!Actor->bActorInitialized) continue;
|
||||
|
||||
if (Actor->IsActorBeingDestroyed())
|
||||
if (Actor->IsPendingKillPending())
|
||||
// if (Actor->IsPendingKill())
|
||||
{
|
||||
ActorsToRemove.push_back(Actor);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -133,25 +161,93 @@ static void ServerReplicateActors_BuildConsiderList(UNetDriver* NetDriver, std::
|
||||
|
||||
if (Actor->Get<ENetRole>(RemoteRoleOffset) == ENetRole::ROLE_None)
|
||||
{
|
||||
ActorsToRemove.push_back(Actor);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We should add a NetDriverName check but I don't believe it is needed.
|
||||
|
||||
// We should check if the actor is initialized here.
|
||||
|
||||
// We should check the level stuff here.
|
||||
|
||||
static auto NetDormancyOffset = Actor->GetOffset("NetDormancy");
|
||||
|
||||
if (Actor->Get<ENetDormancy>(NetDormancyOffset) == ENetDormancy::DORM_Initial && Actor->IsNetStartup())
|
||||
if (Actor->Get<ENetDormancy>(NetDormancyOffset) == ENetDormancy::DORM_Initial && Actor->IsNetStartupActor()) // IsDormInitialStartupActor
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication);
|
||||
CallPreReplication(Actor, NetDriver);
|
||||
// We should check NeedsLoadForClient here.
|
||||
// We should make sure the actor is in the same world here but I don't believe it is needed.
|
||||
|
||||
#ifndef USEOBJECTLIST
|
||||
FNetworkObjectInfo* ActorInfo = new FNetworkObjectInfo;
|
||||
ActorInfo->Actor = Actor;
|
||||
OutConsiderList.push_back(ActorInfo);
|
||||
#else
|
||||
auto TimeSeconds = UGameplayStatics::GetTimeSeconds(World); // Can we do this outside of the loop?
|
||||
|
||||
if (ActorInfo->LastNetReplicateTime == 0)
|
||||
{
|
||||
ActorInfo->LastNetReplicateTime = UGameplayStatics::GetTimeSeconds(World);
|
||||
ActorInfo->OptimalNetUpdateDelta = 1.0f / Actor->GetNetUpdateFrequency();
|
||||
}
|
||||
|
||||
const float ScaleDownStartTime = 2.0f;
|
||||
const float ScaleDownTimeRange = 5.0f;
|
||||
|
||||
const float LastReplicateDelta = TimeSeconds - ActorInfo->LastNetReplicateTime;
|
||||
|
||||
if (LastReplicateDelta > ScaleDownStartTime)
|
||||
{
|
||||
static auto MinNetUpdateFrequencyOffset = Actor->GetOffset("MinNetUpdateFrequency");
|
||||
|
||||
if (Actor->Get<float>(MinNetUpdateFrequencyOffset) == 0.0f)
|
||||
{
|
||||
Actor->Get<float>(MinNetUpdateFrequencyOffset) = 2.0f;
|
||||
}
|
||||
|
||||
const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency(); // Don't go faster than NetUpdateFrequency
|
||||
const float MaxOptimalDelta = max(1.0f / Actor->GetNetUpdateFrequency(), MinOptimalDelta); // Don't go slower than MinNetUpdateFrequency (or NetUpdateFrequency if it's slower)
|
||||
|
||||
const float Alpha = std::clamp((LastReplicateDelta - ScaleDownStartTime) / ScaleDownTimeRange, 0.0f, 1.0f); // should we use fmath?
|
||||
ActorInfo->OptimalNetUpdateDelta = std::lerp(MinOptimalDelta, MaxOptimalDelta, Alpha); // should we use fmath?
|
||||
}
|
||||
|
||||
if (!ActorInfo->bPendingNetUpdate)
|
||||
{
|
||||
constexpr bool bUseAdapativeNetFrequency = false;
|
||||
const float NextUpdateDelta = bUseAdapativeNetFrequency ? ActorInfo->OptimalNetUpdateDelta : 1.0f / Actor->GetNetUpdateFrequency();
|
||||
|
||||
// then set the next update time
|
||||
float ServerTickTime = 1.f / 30;
|
||||
ActorInfo->NextUpdateTime = TimeSeconds + FRand() * ServerTickTime + NextUpdateDelta;
|
||||
static auto TimeOffset = GetOffset("Time");
|
||||
ActorInfo->LastNetUpdateTime = Get<float>(TimeOffset);
|
||||
}
|
||||
|
||||
ActorInfo->bPendingNetUpdate = false;
|
||||
#endif
|
||||
|
||||
OutConsiderList.push_back(ActorInfo.Get());
|
||||
|
||||
static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication);
|
||||
CallPreReplication(Actor, this);
|
||||
}
|
||||
|
||||
#ifndef USEOBJECTLIST
|
||||
Actors.Free();
|
||||
#else
|
||||
for (auto Actor : ActorsToRemove)
|
||||
{
|
||||
if (!Actor)
|
||||
continue;
|
||||
|
||||
/* LOG_INFO(LogDev, "Removing actor: {}", Actor ? Actor->GetFullName() : "InvalidObject");
|
||||
RemoveNetworkActor(Actor);
|
||||
LOG_INFO(LogDev, "Finished removing actor."); */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
using UChannel = UObject;
|
||||
@@ -272,16 +368,21 @@ int32 UNetDriver::ServerReplicateActors()
|
||||
}
|
||||
else */
|
||||
{
|
||||
ServerTickTime = 1.f / ServerTickTime; // 0
|
||||
ServerTickTime = 1.f / ServerTickTime;
|
||||
// bCPUSaturated = DeltaSeconds > 1.2f * ServerTickTime;
|
||||
}
|
||||
|
||||
std::vector<FNetworkObjectInfo*> ConsiderList;
|
||||
// ConsiderList.reserve(GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num());
|
||||
|
||||
#ifdef USEOBJECTLIST
|
||||
ConsiderList.reserve(GetNetworkObjectList().ActiveNetworkObjects.Num());
|
||||
#endif
|
||||
|
||||
// std::cout << "ConsiderList.size(): " << GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num() << '\n';
|
||||
|
||||
ServerReplicateActors_BuildConsiderList(this, ConsiderList);
|
||||
auto World = GetWorld();
|
||||
|
||||
ServerReplicateActors_BuildConsiderList(ConsiderList);
|
||||
|
||||
for (int32 i = 0; i < this->GetClientConnections().Num(); i++)
|
||||
{
|
||||
@@ -347,15 +448,35 @@ int32 UNetDriver::ServerReplicateActors()
|
||||
|
||||
Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1);
|
||||
|
||||
if (Channel) {
|
||||
if (Channel)
|
||||
{
|
||||
SetChannelActor(Channel, Actor);
|
||||
// Channel->Connection = Connection;
|
||||
}
|
||||
|
||||
#ifdef USEOBJECTLIST
|
||||
if (Actor->GetNetUpdateFrequency() < 1.0f)
|
||||
{
|
||||
ActorInfo->NextUpdateTime = UGameplayStatics::GetTimeSeconds(GetWorld()) + 0.2f * FRand();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (Channel)
|
||||
ReplicateActor(Channel);
|
||||
{
|
||||
if (ReplicateActor(Channel))
|
||||
{
|
||||
#ifdef USEOBJECTLIST
|
||||
auto TimeSeconds = UGameplayStatics::GetTimeSeconds(World);
|
||||
const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency();
|
||||
const float MaxOptimalDelta = max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta);
|
||||
const float DeltaBetweenReplications = (TimeSeconds - ActorInfo->LastNetReplicateTime);
|
||||
|
||||
// Choose an optimal time, we choose 70% of the actual rate to allow frequency to go up if needed
|
||||
ActorInfo->OptimalNetUpdateDelta = std::clamp(DeltaBetweenReplications * 0.7f, MinOptimalDelta, MaxOptimalDelta); // should we use fmath?
|
||||
ActorInfo->LastNetReplicateTime = TimeSeconds;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,71 @@
|
||||
#include "NetConnection.h"
|
||||
#include "Array.h"
|
||||
|
||||
#include "WeakObjectPtrTemplates.h"
|
||||
#include "Map.h"
|
||||
#include "SharedPointer.h"
|
||||
#include "Level.h"
|
||||
|
||||
struct FActorDestructionInfo
|
||||
{
|
||||
TWeakObjectPtr<ULevel> Level;
|
||||
TWeakObjectPtr<UObject> ObjOuter;
|
||||
FVector DestroyedPosition;
|
||||
int32 NetGUID;
|
||||
FString PathName;
|
||||
FName StreamingLevelName;
|
||||
};
|
||||
struct FNetworkObjectInfo
|
||||
{
|
||||
/** Pointer to the replicated actor. */
|
||||
AActor* Actor;
|
||||
|
||||
/** WeakPtr to actor. This is cached here to prevent constantly constructing one when needed for (things like) keys in TMaps/TSets */
|
||||
TWeakObjectPtr<AActor> WeakActor;
|
||||
|
||||
/** Next time to consider replicating the actor. Based on FPlatformTime::Seconds(). */
|
||||
double NextUpdateTime;
|
||||
|
||||
/** Last absolute time in seconds since actor actually sent something during replication */
|
||||
double LastNetReplicateTime;
|
||||
|
||||
/** Optimal delta between replication updates based on how frequently actor properties are actually changing */
|
||||
float OptimalNetUpdateDelta;
|
||||
|
||||
/** Last time this actor was updated for replication via NextUpdateTime
|
||||
* @warning: internal net driver time, not related to WorldSettings.TimeSeconds */
|
||||
float LastNetUpdateTime;
|
||||
|
||||
/** Is this object still pending a full net update due to clients that weren't able to replicate the actor at the time of LastNetUpdateTime */
|
||||
uint32 bPendingNetUpdate : 1;
|
||||
|
||||
/** Force this object to be considered relevant for at least one update */
|
||||
uint32 bForceRelevantNextUpdate : 1;
|
||||
|
||||
/** List of connections that this actor is dormant on */
|
||||
TSet<TWeakObjectPtr<UNetConnection>> DormantConnections;
|
||||
|
||||
/** A list of connections that this actor has recently been dormant on, but the actor doesn't have a channel open yet.
|
||||
* These need to be differentiated from actors that the client doesn't know about, but there's no explicit list for just those actors.
|
||||
* (this list will be very transient, with connections being moved off the DormantConnections list, onto this list, and then off once the actor has a channel again)
|
||||
*/
|
||||
TSet<TWeakObjectPtr<UNetConnection>> RecentlyDormantConnections;
|
||||
};
|
||||
|
||||
class FNetworkObjectList
|
||||
{
|
||||
public:
|
||||
typedef TSet<TSharedPtr<FNetworkObjectInfo>> FNetworkObjectSet;
|
||||
|
||||
FNetworkObjectSet AllNetworkObjects;
|
||||
FNetworkObjectSet ActiveNetworkObjects;
|
||||
FNetworkObjectSet ObjectsDormantOnAllConnections;
|
||||
|
||||
TMap<TWeakObjectPtr<UNetConnection>, int32> NumDormantObjectsPerConnection;
|
||||
|
||||
void Remove(AActor* const Actor);
|
||||
};
|
||||
|
||||
class UWorld;
|
||||
|
||||
struct FURL // idk where this actually goes
|
||||
@@ -37,7 +102,10 @@ public:
|
||||
return Get<TArray<UNetConnection*>>(ClientConnectionsOffset);
|
||||
}
|
||||
|
||||
void RemoveNetworkActor(AActor* Actor);
|
||||
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); }
|
||||
int32 ServerReplicateActors();
|
||||
void ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList);
|
||||
FNetworkObjectList& GetNetworkObjectList();
|
||||
};
|
||||
107
Project Reboot 3.0/NetworkObjectList.cpp
Normal file
107
Project Reboot 3.0/NetworkObjectList.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "NetDriver.h"
|
||||
|
||||
void FNetworkObjectList::Remove(AActor* const Actor)
|
||||
{
|
||||
if (Actor == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TSharedPtr<FNetworkObjectInfo>* NetworkObjectInfoPtr = nullptr;
|
||||
|
||||
for (int i = 0; i < AllNetworkObjects.Num(); i++)
|
||||
{
|
||||
auto& CurrentNetworkObject = AllNetworkObjects[i];
|
||||
|
||||
if (CurrentNetworkObject->Actor == Actor)
|
||||
{
|
||||
NetworkObjectInfoPtr = &CurrentNetworkObject;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NetworkObjectInfoPtr == nullptr)
|
||||
{
|
||||
// Sanity check that we're not on the other lists either
|
||||
// check(!ActiveNetworkObjects.Contains(Actor));
|
||||
// check(!ObjectsDormantOnAllConnections.Contains(Actor));
|
||||
// check((ActiveNetworkObjects.Num() + ObjectsDormantOnAllConnections.Num()) == AllNetworkObjects.Num());
|
||||
return;
|
||||
}
|
||||
|
||||
FNetworkObjectInfo* NetworkObjectInfo = NetworkObjectInfoPtr->Get();
|
||||
|
||||
for (int i = 0; i < NetworkObjectInfo->DormantConnections.Num(); i++)
|
||||
{
|
||||
auto& ConnectionIt = NetworkObjectInfo->DormantConnections[i];
|
||||
|
||||
UNetConnection* Connection = ConnectionIt.Get();
|
||||
|
||||
if (Connection == nullptr) // || Connection->State == USOCK_Closed)
|
||||
{
|
||||
NetworkObjectInfo->DormantConnections.Remove(i);
|
||||
// ConnectionIt.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
|
||||
int32* NumDormantObjectsPerConnectionRef = nullptr;
|
||||
|
||||
for (int z = 0; z < NumDormantObjectsPerConnection.Pairs.Num(); z++)
|
||||
{
|
||||
auto& Pair = NumDormantObjectsPerConnection.Pairs[z];
|
||||
|
||||
if (Pair.First.ObjectIndex == Connection->InternalIndex)
|
||||
{
|
||||
NumDormantObjectsPerConnectionRef = &Pair.Second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!NumDormantObjectsPerConnectionRef)
|
||||
{
|
||||
// We should add here TODO MILXNOR
|
||||
}
|
||||
|
||||
// check(NumDormantObjectsPerConnectionRef > 0);
|
||||
|
||||
if (NumDormantObjectsPerConnectionRef)
|
||||
(*NumDormantObjectsPerConnectionRef)--;
|
||||
}
|
||||
|
||||
// Remove this object from all lists
|
||||
|
||||
for (int i = 0; i < AllNetworkObjects.Num(); i++)
|
||||
{
|
||||
auto& CurrentNetworkObject = AllNetworkObjects[i];
|
||||
|
||||
if (CurrentNetworkObject->Actor == Actor)
|
||||
{
|
||||
AllNetworkObjects.Remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ActiveNetworkObjects.Num(); i++)
|
||||
{
|
||||
auto& CurrentActiveNetworkObject = ActiveNetworkObjects[i];
|
||||
|
||||
if (CurrentActiveNetworkObject->Actor == Actor)
|
||||
{
|
||||
ActiveNetworkObjects.Remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < ObjectsDormantOnAllConnections.Num(); i++)
|
||||
{
|
||||
auto& CurrentDormantObject = ObjectsDormantOnAllConnections[i];
|
||||
|
||||
if (CurrentDormantObject->Actor == Actor)
|
||||
{
|
||||
ObjectsDormantOnAllConnections.Remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check((ActiveNetworkObjects.Num() + ObjectsDormantOnAllConnections.Num()) == AllNetworkObjects.Num());
|
||||
}
|
||||
@@ -133,3 +133,8 @@ bool UObject::IsValidLowLevel()
|
||||
}
|
||||
return ChunkedObjects ? ChunkedObjects->IsValid(this) : UnchunkedObjects ? UnchunkedObjects->IsValid(this) : false;
|
||||
}
|
||||
|
||||
FORCEINLINE bool UObject::IsPendingKill() const
|
||||
{
|
||||
return ChunkedObjects ? ChunkedObjects->GetItemByIndex(InternalIndex)->IsPendingKill() : UnchunkedObjects ? UnchunkedObjects->GetItemByIndex(InternalIndex)->IsPendingKill() : false;
|
||||
}
|
||||
@@ -90,6 +90,25 @@ public:
|
||||
|
||||
void AddToRoot();
|
||||
bool IsValidLowLevel();
|
||||
FORCEINLINE bool IsPendingKill() const;
|
||||
|
||||
// static class UClass* StaticClass();
|
||||
};
|
||||
|
||||
/* struct FInternalUObjectBaseUtilityIsValidFlagsChecker
|
||||
{
|
||||
FORCEINLINE static bool CheckObjectValidBasedOnItsFlags(const UObject* Test)
|
||||
{
|
||||
// Here we don't really check if the flags match but if the end result is the same
|
||||
checkSlow(GUObjectArray.IndexToObject(Test->InternalIndex)->HasAnyFlags(EInternalObjectFlags::PendingKill | EInternalObjectFlags::Garbage) == Test->HasAnyFlags(RF_InternalPendingKill | RF_InternalGarbage));
|
||||
return !Test->HasAnyFlags(RF_InternalPendingKill | RF_InternalGarbage);
|
||||
}
|
||||
}; */
|
||||
|
||||
FORCEINLINE bool IsValidChecked(const UObject* Test)
|
||||
{
|
||||
// if (!Test)
|
||||
// return false;
|
||||
|
||||
return true; // FInternalUObjectBaseUtilityIsValidFlagsChecker::CheckObjectValidBasedOnItsFlags(Test);
|
||||
}
|
||||
@@ -50,6 +50,7 @@ enum class EInternalObjectFlags : int
|
||||
AsyncLoading = 1 << 27, ///< Object is being asynchronously loaded.
|
||||
Unreachable = 1 << 28, ///< Object is not reachable on the object graph.
|
||||
// PendingKill UE_DEPRECATED(5.0, "PendingKill flag should no longer be used. Use Garbage flag instead.") = 1 << 29, ///< Objects that are pending destruction (invalid for gameplay but valid objects). This flag is mirrored in EObjectFlags as RF_PendingKill for performance
|
||||
PendingKill = 1 << 29,
|
||||
RootSet = 1 << 30, ///< Object will not be garbage collected, even if unreferenced.
|
||||
PendingConstruction = 1 << 31 ///< Object didn't have its class constructor called yet (only the UObjectBase one to initialize its most basic members)
|
||||
|
||||
|
||||
@@ -209,10 +209,12 @@
|
||||
<ClCompile Include="InventoryManagementLibrary.cpp" />
|
||||
<ClCompile Include="KismetMathLibrary.cpp" />
|
||||
<ClCompile Include="KismetStringLibrary.cpp" />
|
||||
<ClCompile Include="Level.cpp" />
|
||||
<ClCompile Include="LevelActor.cpp" />
|
||||
<ClCompile Include="NameTypes.cpp" />
|
||||
<ClCompile Include="NetConnection.h" />
|
||||
<ClCompile Include="NetDriver.cpp" />
|
||||
<ClCompile Include="NetworkObjectList.cpp" />
|
||||
<ClCompile Include="Object.cpp" />
|
||||
<ClCompile Include="PlayerController.cpp" />
|
||||
<ClCompile Include="PlayerState.cpp" />
|
||||
@@ -295,6 +297,7 @@
|
||||
<ClInclude Include="KismetMathLibrary.h" />
|
||||
<ClInclude Include="KismetStringLibrary.h" />
|
||||
<ClInclude Include="KismetSystemLibrary.h" />
|
||||
<ClInclude Include="Level.h" />
|
||||
<ClInclude Include="log.h" />
|
||||
<ClInclude Include="Map.h" />
|
||||
<ClInclude Include="MegaStormManager.h" />
|
||||
@@ -315,6 +318,7 @@
|
||||
<ClInclude Include="Rotator.h" />
|
||||
<ClInclude Include="ScriptInterface.h" />
|
||||
<ClInclude Include="Set.h" />
|
||||
<ClInclude Include="SharedPointer.h" />
|
||||
<ClInclude Include="SoftObjectPath.h" />
|
||||
<ClInclude Include="SoftObjectPtr.h" />
|
||||
<ClInclude Include="SparseArray.h" />
|
||||
@@ -328,6 +332,7 @@
|
||||
<ClInclude Include="Vector.h" />
|
||||
<ClInclude Include="vehicles.h" />
|
||||
<ClInclude Include="WeakObjectPtr.h" />
|
||||
<ClInclude Include="WeakObjectPtrTemplates.h" />
|
||||
<ClInclude Include="World.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -167,6 +167,12 @@
|
||||
<ClCompile Include="FortPlayerStateAthena.cpp">
|
||||
<Filter>FortniteGame\Source\FortniteGame\Private\Player</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Level.cpp">
|
||||
<Filter>Engine\Source\Runtime\Engine\Private</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NetworkObjectList.cpp">
|
||||
<Filter>Engine\Source\Runtime\Engine\Private</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="log.h" />
|
||||
@@ -482,6 +488,15 @@
|
||||
<ClInclude Include="FortQuickBars.h">
|
||||
<Filter>FortniteGame\Source\FortniteGame\Public\Items</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WeakObjectPtrTemplates.h">
|
||||
<Filter>Engine\Source\Runtime\CoreUObject\Public\UObject</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SharedPointer.h">
|
||||
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Level.h">
|
||||
<Filter>Engine\Source\Runtime\Engine\Classes\Engine</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Engine">
|
||||
@@ -628,9 +643,6 @@
|
||||
<Filter Include="Engine\Source\Runtime\GameplayTags\Classes">
|
||||
<UniqueIdentifier>{247d4c62-23f7-4964-8879-5a0d65c44a73}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Engine\Source\Runtime\Core\Public\Templates">
|
||||
<UniqueIdentifier>{31a7f342-8b7c-4594-a24d-c4dd5c9d230d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="FortniteGame\Source\FortniteGame\Public\Weapons">
|
||||
<UniqueIdentifier>{bcb0d983-0b85-4ca6-9fac-6567c7d79921}</UniqueIdentifier>
|
||||
</Filter>
|
||||
@@ -667,6 +679,9 @@
|
||||
<Filter Include="Engine\Source\Runtime\CoreUObject\Public\Misc">
|
||||
<UniqueIdentifier>{915f7622-6003-445e-a43f-04d5c7e13b49}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Engine\Source\Runtime\Core\Public\Templates">
|
||||
<UniqueIdentifier>{31a7f342-8b7c-4594-a24d-c4dd5c9d230d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="UnrealEngine.cpp">
|
||||
|
||||
@@ -32,7 +32,173 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template<typename InElementType> //, typename KeyFuncs, typename Allocator>
|
||||
template <typename SetType>
|
||||
class TSet
|
||||
{
|
||||
private:
|
||||
friend TSparseArray;
|
||||
|
||||
public:
|
||||
typedef TSetElement<SetType> ElementType;
|
||||
typedef TSparseArrayElementOrListLink<ElementType> ArrayElementType;
|
||||
|
||||
public:
|
||||
TSparseArray<ElementType> Elements;
|
||||
|
||||
mutable TInlineAllocator<1>::ForElementType<int> Hash;
|
||||
mutable int32 HashSize;
|
||||
|
||||
public:
|
||||
class FBaseIterator
|
||||
{
|
||||
private:
|
||||
TSet<SetType>& IteratedSet;
|
||||
TSparseArray<ElementType>::FBaseIterator ElementIt;
|
||||
|
||||
public:
|
||||
FORCEINLINE FBaseIterator(const TSet<SetType>& InSet, TSparseArray<TSetElement<SetType>>::FBaseIterator InElementIt)
|
||||
: IteratedSet(const_cast<TSet<SetType>&>(InSet))
|
||||
, ElementIt(InElementIt)
|
||||
{
|
||||
}
|
||||
|
||||
FORCEINLINE explicit operator bool() const
|
||||
{
|
||||
return (bool)ElementIt;
|
||||
}
|
||||
FORCEINLINE TSet<SetType>::FBaseIterator& operator++()
|
||||
{
|
||||
++ElementIt;
|
||||
return *this;
|
||||
}
|
||||
FORCEINLINE bool operator==(const TSet<SetType>::FBaseIterator& OtherIt) const
|
||||
{
|
||||
return ElementIt == OtherIt.ElementIt;
|
||||
}
|
||||
FORCEINLINE bool operator!=(const TSet<SetType>::FBaseIterator& OtherIt) const
|
||||
{
|
||||
return ElementIt != OtherIt.ElementIt;
|
||||
}
|
||||
FORCEINLINE TSet<SetType>::FBaseIterator& operator=(TSet<SetType>::FBaseIterator& OtherIt)
|
||||
{
|
||||
return ElementIt = OtherIt.ElementIt;
|
||||
}
|
||||
FORCEINLINE SetType& operator*()
|
||||
{
|
||||
return (*ElementIt).Value;
|
||||
}
|
||||
FORCEINLINE const SetType& operator*() const
|
||||
{
|
||||
return &((*ElementIt).Value);
|
||||
}
|
||||
FORCEINLINE SetType* operator->()
|
||||
{
|
||||
return &((*ElementIt).Value);
|
||||
}
|
||||
FORCEINLINE const SetType* operator->() const
|
||||
{
|
||||
return &(*ElementIt).Value;
|
||||
}
|
||||
FORCEINLINE const int32 GetIndex() const
|
||||
{
|
||||
return ElementIt.GetIndex();
|
||||
}
|
||||
FORCEINLINE ElementType& GetSetElement()
|
||||
{
|
||||
return *ElementIt;
|
||||
}
|
||||
FORCEINLINE const ElementType& GetSetElement() const
|
||||
{
|
||||
return *ElementIt;
|
||||
}
|
||||
FORCEINLINE bool IsElementValid() const
|
||||
{
|
||||
return ElementIt.IsElementValid();
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
FORCEINLINE TSet<SetType>::FBaseIterator begin()
|
||||
{
|
||||
return TSet<SetType>::FBaseIterator(*this, Elements.begin());
|
||||
}
|
||||
FORCEINLINE const TSet<SetType>::FBaseIterator begin() const
|
||||
{
|
||||
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)
|
||||
{
|
||||
return Elements[Index].ElementData.Value;
|
||||
}
|
||||
|
||||
FORCEINLINE int32 Num() const
|
||||
{
|
||||
return Elements.Num();
|
||||
}
|
||||
FORCEINLINE bool IsValid() const
|
||||
{
|
||||
return Elements.Data.Data != nullptr && Elements.AllocationFlags.MaxBits > 0;
|
||||
}
|
||||
FORCEINLINE TSparseArray<ElementType>& GetElements()
|
||||
{
|
||||
return Elements;
|
||||
}
|
||||
FORCEINLINE const TSparseArray<ElementType>& GetElements() const
|
||||
{
|
||||
return Elements;
|
||||
}
|
||||
FORCEINLINE const TBitArray& GetAllocationFlags() const
|
||||
{
|
||||
return Elements.GetAllocationFlags();
|
||||
}
|
||||
FORCEINLINE bool IsIndexValid(int32 IndexToCheck) const
|
||||
{
|
||||
return Elements.IsIndexValid(IndexToCheck);
|
||||
}
|
||||
FORCEINLINE const bool Contains(const SetType& ElementToLookFor) const
|
||||
{
|
||||
if (Num() <= 0)
|
||||
return false;
|
||||
|
||||
for (SetType Element : *this)
|
||||
{
|
||||
if (Element == ElementToLookFor)
|
||||
return true;
|
||||
}
|
||||
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 -1;
|
||||
}
|
||||
FORCEINLINE bool Remove(const SetType& ElementToRemove)
|
||||
{
|
||||
return Elements.RemoveAt(Find(ElementToRemove));
|
||||
}
|
||||
FORCEINLINE bool Remove(int Index)
|
||||
{
|
||||
return Elements.RemoveAt(Index);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* template<typename InElementType> //, typename KeyFuncs, typename Allocator>
|
||||
class TSet
|
||||
{
|
||||
public:
|
||||
@@ -43,4 +209,4 @@ public:
|
||||
|
||||
mutable TInlineAllocator<1>::ForElementType<int> Hash;
|
||||
mutable int32 HashSize;
|
||||
};
|
||||
}; */
|
||||
36
Project Reboot 3.0/SharedPointer.h
Normal file
36
Project Reboot 3.0/SharedPointer.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
template< class ObjectType>
|
||||
class TSharedPtr
|
||||
{
|
||||
public:
|
||||
ObjectType* Object;
|
||||
|
||||
int32 SharedReferenceCount;
|
||||
int32 WeakReferenceCount;
|
||||
|
||||
FORCEINLINE ObjectType* Get()
|
||||
{
|
||||
return Object;
|
||||
}
|
||||
FORCEINLINE ObjectType* Get() const
|
||||
{
|
||||
return Object;
|
||||
}
|
||||
FORCEINLINE ObjectType& operator*()
|
||||
{
|
||||
return *Object;
|
||||
}
|
||||
FORCEINLINE const ObjectType& operator*() const
|
||||
{
|
||||
return *Object;
|
||||
}
|
||||
FORCEINLINE ObjectType* operator->()
|
||||
{
|
||||
return Object;
|
||||
}
|
||||
FORCEINLINE ObjectType* operator->() const
|
||||
{
|
||||
return Object;
|
||||
}
|
||||
};
|
||||
@@ -50,6 +50,86 @@ public:
|
||||
int32 FirstFreeIndex;
|
||||
int32 NumFreeIndices;
|
||||
|
||||
FORCEINLINE int32 Num() const
|
||||
{
|
||||
return Data.Num() - NumFreeIndices;
|
||||
}
|
||||
|
||||
class FBaseIterator
|
||||
{
|
||||
private:
|
||||
TSparseArray<ArrayType>& IteratedArray;
|
||||
TBitArray::FSetBitIterator BitArrayIt;
|
||||
|
||||
public:
|
||||
FORCEINLINE FBaseIterator(const TSparseArray<ArrayType>& Array, const TBitArray::FSetBitIterator BitIterator)
|
||||
: IteratedArray(const_cast<TSparseArray<ArrayType>&>(Array))
|
||||
, BitArrayIt(const_cast<TBitArray::FSetBitIterator&>(BitIterator))
|
||||
{
|
||||
}
|
||||
|
||||
FORCEINLINE explicit operator bool() const
|
||||
{
|
||||
return (bool)BitArrayIt;
|
||||
}
|
||||
FORCEINLINE TSparseArray<ArrayType>::FBaseIterator& operator++()
|
||||
{
|
||||
++BitArrayIt;
|
||||
return *this;
|
||||
}
|
||||
FORCEINLINE ArrayType& operator*()
|
||||
{
|
||||
return IteratedArray[BitArrayIt.GetIndex()].ElementData;
|
||||
}
|
||||
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
|
||||
{
|
||||
return BitArrayIt.GetIndex();
|
||||
}
|
||||
FORCEINLINE bool IsElementValid() const
|
||||
{
|
||||
return *BitArrayIt;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
FORCEINLINE TSparseArray<ArrayType>::FBaseIterator begin()
|
||||
{
|
||||
return TSparseArray<ArrayType>::FBaseIterator(*this, TBitArray::FSetBitIterator(AllocationFlags, 0));
|
||||
}
|
||||
FORCEINLINE const TSparseArray<ArrayType>::FBaseIterator begin() const
|
||||
{
|
||||
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)
|
||||
{
|
||||
return *(FSparseArrayElement*)&Data.at(Index).ElementData;
|
||||
@@ -58,9 +138,62 @@ public:
|
||||
{
|
||||
return *(const FSparseArrayElement*)&Data.at(Index).ElementData;
|
||||
}
|
||||
|
||||
FORCEINLINE int32 Num() const
|
||||
FORCEINLINE int32 GetNumFreeIndices() const
|
||||
{
|
||||
return Data.Num() - NumFreeIndices;
|
||||
return NumFreeIndices;
|
||||
}
|
||||
FORCEINLINE int32 GetFirstFreeIndex() const
|
||||
{
|
||||
return FirstFreeIndex;
|
||||
}
|
||||
FORCEINLINE const TArray<FSparseArrayElement>& GetData() const
|
||||
{
|
||||
return Data;
|
||||
}
|
||||
FORCEINLINE const TBitArray& GetAllocationFlags() const
|
||||
{
|
||||
return AllocationFlags;
|
||||
}
|
||||
FORCEINLINE bool IsIndexValid(int32 IndexToCheck) const
|
||||
{
|
||||
return AllocationFlags.IsSet(IndexToCheck);
|
||||
}
|
||||
|
||||
FORCEINLINE bool RemoveAt(const int32 IndexToRemove)
|
||||
{
|
||||
if (IndexToRemove >= 0 && IndexToRemove < Data.Num() && AllocationFlags.IsSet(IndexToRemove))
|
||||
{
|
||||
int32 PreviousFreeIndex = -1;
|
||||
int32 NextFreeIndex = -1;
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
@@ -12,6 +12,11 @@ struct FUObjectItem
|
||||
int32 ClusterRootIndex;
|
||||
int32 SerialNumber;
|
||||
|
||||
FORCEINLINE bool IsPendingKill() const
|
||||
{
|
||||
return !!(Flags & int32(EInternalObjectFlags::PendingKill));
|
||||
}
|
||||
|
||||
FORCEINLINE void SetFlag(EInternalObjectFlags FlagToSet)
|
||||
{
|
||||
// static_assert(sizeof(int32) == sizeof(Flags), "Flags must be 32-bit for atomics.");
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "UObjectArray.h"
|
||||
|
||||
struct FWeakObjectPtr
|
||||
{
|
||||
public:
|
||||
int ObjectIndex;
|
||||
int ObjectSerialNumber;
|
||||
|
||||
UObject* Get()
|
||||
{
|
||||
return ChunkedObjects ? ChunkedObjects->GetObjectByIndex(ObjectIndex) : UnchunkedObjects ? UnchunkedObjects->GetObjectByIndex(ObjectIndex) : nullptr;
|
||||
}
|
||||
};
|
||||
16
Project Reboot 3.0/WeakObjectPtrTemplates.h
Normal file
16
Project Reboot 3.0/WeakObjectPtrTemplates.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "WeakObjectPtr.h"
|
||||
#include "Object.h"
|
||||
|
||||
template<class T = UObject, class TWeakObjectPtrBase = FWeakObjectPtr>
|
||||
struct TWeakObjectPtr;
|
||||
|
||||
template<class T, class TWeakObjectPtrBase>
|
||||
struct TWeakObjectPtr : public TWeakObjectPtrBase
|
||||
{
|
||||
T* Get()
|
||||
{
|
||||
return (T*)TWeakObjectPtrBase::Get();
|
||||
}
|
||||
};
|
||||
@@ -395,7 +395,7 @@ std::vector<uint64> Addresses::GetFunctionsToNull()
|
||||
if (Fortnite_Version > 2.5 && Engine_Version == 420)
|
||||
{
|
||||
toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 57 48 81 EC ? ? ? ? 4C 8B 82 ? ? ? ? 48 8B F9 0F 29 70 E8 0F 29 78 D8").Get()); // Pawn Overlap
|
||||
toNull.push_back(Memcury::Scanner::FindPattern("E8 ? ? ? ? EB 26 40 38 3D ? ? ? ?").RelativeOffset(1).Get()); // collectgarbage
|
||||
// toNull.push_back(Memcury::Scanner::FindPattern("E8 ? ? ? ? EB 26 40 38 3D ? ? ? ?").RelativeOffset(1).Get()); // collectgarbage
|
||||
}
|
||||
|
||||
if (Engine_Version == 421)
|
||||
|
||||
@@ -61,6 +61,34 @@ static __int64 DispatchRequestHook(__int64 a1, __int64* a2, int a3)
|
||||
return DispatchRequestOriginal(a1, a2, 3);
|
||||
}
|
||||
|
||||
void (*ApplyHomebaseEffectsOnPlayerSetupOriginal)(
|
||||
__int64* GameState,
|
||||
__int64 a2,
|
||||
__int64 a3,
|
||||
__int64 a4,
|
||||
UObject* Hero,
|
||||
char a6,
|
||||
unsigned __int8 a7);
|
||||
|
||||
void __fastcall ApplyHomebaseEffectsOnPlayerSetupHook(
|
||||
__int64* GameState,
|
||||
__int64 a2,
|
||||
__int64 a3,
|
||||
__int64 a4,
|
||||
UObject* Hero,
|
||||
char a6,
|
||||
unsigned __int8 a7)
|
||||
{
|
||||
LOG_INFO(LogDev, "Old hero: {}", Hero ? Hero->GetFullName() : "InvalidObject");
|
||||
|
||||
auto HeroType = FindObject<UFortItemDefinition>("/Game/Athena/Heroes/HID_030_Athena_Commando_M_Halloween.HID_030_Athena_Commando_M_Halloween");
|
||||
|
||||
static auto ItemDefinitionOffset = Hero->GetOffset("ItemDefinition");
|
||||
Hero->Get<UFortItemDefinition*>(ItemDefinitionOffset) = HeroType;
|
||||
|
||||
return ApplyHomebaseEffectsOnPlayerSetupOriginal(GameState, a2, a3, a4, Hero, a6, a7);
|
||||
}
|
||||
|
||||
DWORD WINAPI Main(LPVOID)
|
||||
{
|
||||
InitLogger();
|
||||
@@ -213,6 +241,8 @@ DWORD WINAPI Main(LPVOID)
|
||||
if (func == 0)
|
||||
continue;
|
||||
|
||||
LOG_INFO(LogDev, "Nulling 0x{:x}", func - __int64(GetModuleHandleW(0)));
|
||||
|
||||
DWORD dwProtection;
|
||||
VirtualProtect((PVOID)func, 1, PAGE_EXECUTE_READWRITE, &dwProtection);
|
||||
|
||||
@@ -228,11 +258,16 @@ DWORD WINAPI Main(LPVOID)
|
||||
|
||||
// Globals::bAbilitiesEnabled = Engine_Version < 500;
|
||||
|
||||
if (Fortnite_Version == 1.11)
|
||||
{
|
||||
auto ApplyHomebaseEffectsOnPlayerSetupAddr = Memcury::Scanner::FindPattern("40 55 53 57 41 54 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 00 4C 8B BD ? ? ? ? 49").Get();
|
||||
|
||||
Hooking::MinHook::Hook((PVOID)ApplyHomebaseEffectsOnPlayerSetupAddr, ApplyHomebaseEffectsOnPlayerSetupHook, (PVOID*)&ApplyHomebaseEffectsOnPlayerSetupOriginal);
|
||||
}
|
||||
|
||||
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameMode.ReadyToStartMatch"), AFortGameModeAthena::Athena_ReadyToStartMatchHook,
|
||||
(PVOID*)&AFortGameModeAthena::Athena_ReadyToStartMatchOriginal, false);
|
||||
|
||||
// return false;
|
||||
|
||||
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameModeBase.SpawnDefaultPawnFor"),
|
||||
AGameModeBase::SpawnDefaultPawnForHook, nullptr, false);
|
||||
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameModeBase.HandleStartingNewPlayer"), AFortGameModeAthena::Athena_HandleStartingNewPlayerHook,
|
||||
@@ -576,6 +611,56 @@ DWORD WINAPI Main(LPVOID)
|
||||
|
||||
else if (GetAsyncKeyState(VK_F8) & 1)
|
||||
{
|
||||
auto GameMode = (AFortGameMode*)GetWorld()->GetGameMode();
|
||||
auto GameState = GameMode->GetGameState();
|
||||
|
||||
if (Fortnite_Version == 1.11)
|
||||
{
|
||||
static auto OverrideBattleBusSkin = FindObject("/Game/Athena/Items/Cosmetics/BattleBuses/BBID_WinterBus.BBID_WinterBus");
|
||||
LOG_INFO(LogDev, "OverrideBattleBusSkin: {}", __int64(OverrideBattleBusSkin));
|
||||
|
||||
if (OverrideBattleBusSkin)
|
||||
{
|
||||
static auto AssetManagerOffset = GetEngine()->GetOffset("AssetManager");
|
||||
auto AssetManager = GetEngine()->Get(AssetManagerOffset);
|
||||
|
||||
if (AssetManager)
|
||||
{
|
||||
static auto AthenaGameDataOffset = AssetManager->GetOffset("AthenaGameData");
|
||||
auto AthenaGameData = AssetManager->Get(AthenaGameDataOffset);
|
||||
|
||||
if (AthenaGameData)
|
||||
{
|
||||
static auto DefaultBattleBusSkinOffset = AthenaGameData->GetOffset("DefaultBattleBusSkin");
|
||||
AthenaGameData->Get(DefaultBattleBusSkinOffset) = OverrideBattleBusSkin;
|
||||
}
|
||||
}
|
||||
|
||||
static auto DefaultBattleBusOffset = GameState->GetOffset("DefaultBattleBus");
|
||||
GameState->Get(DefaultBattleBusOffset) = OverrideBattleBusSkin;
|
||||
|
||||
static auto FortAthenaAircraftClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaAircraft");
|
||||
auto AllAircrafts = UGameplayStatics::GetAllActorsOfClass(GetWorld(), FortAthenaAircraftClass);
|
||||
|
||||
for (int i = 0; i < AllAircrafts.Num(); i++)
|
||||
{
|
||||
auto Aircraft = AllAircrafts.at(i);
|
||||
|
||||
static auto DefaultBusSkinOffset = Aircraft->GetOffset("DefaultBusSkin");
|
||||
Aircraft->Get(DefaultBusSkinOffset) = OverrideBattleBusSkin;
|
||||
|
||||
static auto SpawnedCosmeticActorOffset = Aircraft->GetOffset("SpawnedCosmeticActor");
|
||||
auto SpawnedCosmeticActor = Aircraft->Get<AActor*>(SpawnedCosmeticActorOffset);
|
||||
|
||||
if (SpawnedCosmeticActor)
|
||||
{
|
||||
static auto ActiveSkinOffset = SpawnedCosmeticActor->GetOffset("ActiveSkin");
|
||||
SpawnedCosmeticActor->Get(ActiveSkinOffset) = OverrideBattleBusSkin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float Duration = 0;
|
||||
float EarlyDuration = Duration;
|
||||
|
||||
@@ -583,9 +668,6 @@ DWORD WINAPI Main(LPVOID)
|
||||
|
||||
LOG_INFO(LogDev, "Starting bus!");
|
||||
|
||||
auto GameMode = (AFortGameMode*)GetWorld()->GetGameMode();
|
||||
auto GameState = GameMode->GetGameState();
|
||||
|
||||
GameState->Get<float>("WarmupCountdownEndTime") = 0;
|
||||
GameMode->Get<float>("WarmupCountdownDuration") = 0;
|
||||
|
||||
@@ -602,6 +684,8 @@ DWORD WINAPI Main(LPVOID)
|
||||
}
|
||||
|
||||
else if (GetAsyncKeyState(VK_F10) & 1)
|
||||
{
|
||||
if (Engine_Version < 424)
|
||||
{
|
||||
FString LevelA = Engine_Version < 424
|
||||
? L"open Athena_Terrain" : Engine_Version >= 500 ? Engine_Version >= 501
|
||||
@@ -625,9 +709,14 @@ DWORD WINAPI Main(LPVOID)
|
||||
((AGameMode*)GetWorld()->GetGameMode())->RestartGame();
|
||||
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), LevelA, nullptr);
|
||||
// UGameplayStatics::OpenLevel(GetWorld(), UKismetStringLibrary::Conv_StringToName(LevelA), true, FString());
|
||||
LOG_INFO(LogDev, "Restarting!");
|
||||
LOG_INFO(LogGame, "Restarting!");
|
||||
AmountOfRestarts++;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LogGame, "Restarting is not supported on chapter 2 and above!");
|
||||
}
|
||||
}
|
||||
|
||||
Sleep(1000 / 30);
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ static inline uint64 FindGetPlayerViewpoint()
|
||||
|
||||
LOG_INFO(LogDev, "GetPlayerViewpoint StringRef: 0x{:x}", __int64(Addrr) - __int64(GetModuleHandleW(0)));
|
||||
|
||||
for (int i = 0; i < 1200; i++)
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x55)
|
||||
{
|
||||
@@ -337,8 +337,9 @@ static inline uint64 FindGetPlayerViewpoint()
|
||||
return Addrr - i;
|
||||
}
|
||||
|
||||
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0xC3) // hmm
|
||||
if (Fortnite_Version == 7.20 && *(uint8_t*)(uint8_t*)(Addrr - i) == 0xC3) // hmm scuffed lmfao
|
||||
{
|
||||
LOG_INFO(LogDev, "Hit C3!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user