mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
fix s11 idk
This commit is contained in:
@@ -174,6 +174,20 @@ const AActor* AActor::GetNetOwner() const
|
|||||||
return GetNetOwnerOriginal(this);
|
return GetNetOwnerOriginal(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AActor::GetActorEyesViewPoint(FVector* OutLocation, FRotator* OutRotation) const
|
||||||
|
{
|
||||||
|
static auto GetActorEyesViewPointFn = FindObject<UFunction>("/Script/Engine.Actor.GetActorEyesViewPoint");
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct FVector OutLocation; // (Parm, OutParm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
struct FRotator OutRotation; // (Parm, OutParm, ZeroConstructor, IsPlainOldData, NoDestructor, NativeAccessSpecifierPublic)
|
||||||
|
} AActor_GetActorEyesViewPoint_Params{};
|
||||||
|
this->ProcessEvent(GetActorEyesViewPointFn, &AActor_GetActorEyesViewPoint_Params);
|
||||||
|
|
||||||
|
*OutLocation = AActor_GetActorEyesViewPoint_Params.OutLocation;
|
||||||
|
*OutRotation = AActor_GetActorEyesViewPoint_Params.OutRotation;
|
||||||
|
}
|
||||||
|
|
||||||
bool AActor::IsAlwaysRelevant()
|
bool AActor::IsAlwaysRelevant()
|
||||||
{
|
{
|
||||||
static auto bAlwaysRelevantOffset = GetOffset("bAlwaysRelevant");
|
static auto bAlwaysRelevantOffset = GetOffset("bAlwaysRelevant");
|
||||||
|
|||||||
@@ -44,11 +44,18 @@ public:
|
|||||||
float& GetNetUpdateFrequency();
|
float& GetNetUpdateFrequency();
|
||||||
float& GetMinNetUpdateFrequency();
|
float& GetMinNetUpdateFrequency();
|
||||||
const AActor* GetNetOwner() const;
|
const AActor* GetNetOwner() const;
|
||||||
|
void GetActorEyesViewPoint(FVector* OutLocation, FRotator* OutRotation) const;
|
||||||
|
|
||||||
bool IsRelevancyOwnerFor(const AActor* ReplicatedActor, const AActor* ActorOwner, const AActor* ConnectionActor) const
|
bool IsRelevancyOwnerFor(const AActor* ReplicatedActor, const AActor* ActorOwner, const AActor* ConnectionActor) const
|
||||||
{
|
{
|
||||||
// we should call virtual function but eh
|
// we should call virtual function but eh
|
||||||
return (ActorOwner == this);
|
// return (ActorOwner == this);
|
||||||
|
|
||||||
|
static auto IsRelevancyOwnerForOffset = 0x428;
|
||||||
|
bool (*IsRelevancyOwnerForOriginal)(const AActor* Actor, const AActor * ReplicatedActor, const AActor * ActorOwner, const AActor * ConnectionActor) =
|
||||||
|
decltype(IsRelevancyOwnerForOriginal)(this->VFTable[IsRelevancyOwnerForOffset / 8]);
|
||||||
|
|
||||||
|
return IsRelevancyOwnerForOriginal(this, ReplicatedActor, ActorOwner, ConnectionActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class UClass* StaticClass();
|
static class UClass* StaticClass();
|
||||||
|
|||||||
@@ -30,11 +30,89 @@ public:
|
|||||||
inline int Num() const { return ArrayNum; }
|
inline int Num() const { return ArrayNum; }
|
||||||
inline int size() const { return ArrayNum; }
|
inline int size() const { return ArrayNum; }
|
||||||
|
|
||||||
|
/* FORCENOINLINE void ResizeTo(int32 NewMax)
|
||||||
|
{
|
||||||
|
if (NewMax)
|
||||||
|
{
|
||||||
|
NewMax = AllocatorInstance.CalculateSlackReserve(NewMax, sizeof(ElementType));
|
||||||
|
}
|
||||||
|
if (NewMax != ArrayMax)
|
||||||
|
{
|
||||||
|
ArrayMax = NewMax;
|
||||||
|
AllocatorInstance.ResizeAllocation(ArrayNum, ArrayMax, sizeof(ElementType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Empty(int32 Slack = 0)
|
||||||
|
{
|
||||||
|
// DestructItems(GetData(), ArrayNum);
|
||||||
|
|
||||||
|
// checkSlow(Slack >= 0);
|
||||||
|
ArrayNum = 0;
|
||||||
|
|
||||||
|
if (ArrayMax != Slack)
|
||||||
|
{
|
||||||
|
ResizeTo(Slack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset(int32 NewSize = 0)
|
||||||
|
{
|
||||||
|
// If we have space to hold the excepted size, then don't reallocate
|
||||||
|
if (NewSize <= ArrayMax)
|
||||||
|
{
|
||||||
|
// DestructItems(GetData(), ArrayNum);
|
||||||
|
ArrayNum = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Empty(NewSize);
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
void RemoveAtImpl(int32 Index, int32 Count, bool bAllowShrinking)
|
||||||
|
{
|
||||||
|
if (Count)
|
||||||
|
{
|
||||||
|
// CheckInvariants();
|
||||||
|
// checkSlow((Count >= 0) & (Index >= 0) & (Index + Count <= ArrayNum));
|
||||||
|
|
||||||
|
// DestructItems(GetData() + Index, Count); // TODO milxnor
|
||||||
|
|
||||||
|
// Skip memmove in the common case that there is nothing to move.
|
||||||
|
int32 NumToMove = ArrayNum - Index - Count;
|
||||||
|
if (NumToMove)
|
||||||
|
{
|
||||||
|
/* FMemory::Memmove
|
||||||
|
(
|
||||||
|
(uint8*)AllocatorInstance.GetAllocation() + (Index) * sizeof(ElementType),
|
||||||
|
(uint8*)AllocatorInstance.GetAllocation() + (Index + Count) * sizeof(ElementType),
|
||||||
|
NumToMove * sizeof(ElementType)
|
||||||
|
); */
|
||||||
|
// memmove(Data + (Index) * sizeof(InElementType), Data + (Index + Count) * sizeof(InElementType), NumToMove * sizeof(InElementType)); // i think this wrong
|
||||||
|
}
|
||||||
|
ArrayNum -= Count;
|
||||||
|
|
||||||
|
if (bAllowShrinking)
|
||||||
|
{
|
||||||
|
// ResizeShrink(); // TODO milxnor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
FORCEINLINE SizeType CalculateSlackGrow(SizeType NumElements, SizeType NumAllocatedElements, SIZE_T NumBytesPerElement) const
|
FORCEINLINE SizeType CalculateSlackGrow(SizeType NumElements, SizeType NumAllocatedElements, SIZE_T NumBytesPerElement) const
|
||||||
{
|
{
|
||||||
return ArrayMax - NumElements;
|
return ArrayMax - NumElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename CountType>
|
||||||
|
FORCEINLINE void RemoveAt(int32 Index, CountType Count, bool bAllowShrinking = true)
|
||||||
|
{
|
||||||
|
// static_assert(!TAreTypesEqual<CountType, bool>::Value, "TArray::RemoveAt: unexpected bool passed as the Count argument");
|
||||||
|
RemoveAtImpl(Index, Count, bAllowShrinking);
|
||||||
|
}
|
||||||
|
|
||||||
void Reserve(int Number, size_t Size = sizeof(InElementType))
|
void Reserve(int Number, size_t Size = sizeof(InElementType))
|
||||||
{
|
{
|
||||||
// LOG_INFO(LogDev, "ArrayNum {}", ArrayNum);
|
// LOG_INFO(LogDev, "ArrayNum {}", ArrayNum);
|
||||||
|
|||||||
@@ -22,4 +22,6 @@ public:
|
|||||||
static auto BitfieldOffset = GetOffset("Connection") + 8;
|
static auto BitfieldOffset = GetOffset("Connection") + 8;
|
||||||
return ((PlaceholderBitfield*)(__int64(this) + BitfieldOffset))->Third;
|
return ((PlaceholderBitfield*)(__int64(this) + BitfieldOffset))->Third;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 IsNetReady(bool Saturate);
|
||||||
};
|
};
|
||||||
16
Project Reboot 3.0/DataChannel.cpp
Normal file
16
Project Reboot 3.0/DataChannel.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include "Channel.h"
|
||||||
|
#include "NetConnection.h"
|
||||||
|
|
||||||
|
int32 UChannel::IsNetReady(bool Saturate)
|
||||||
|
{
|
||||||
|
static auto NumOutRecOffset = 0x4C;
|
||||||
|
|
||||||
|
if (*(int*)(__int64(this) + NumOutRecOffset) < 255)
|
||||||
|
{
|
||||||
|
static auto ConnectionOffset = GetOffset("Connection");
|
||||||
|
auto Connection = Get<UNetConnection*>(ConnectionOffset);
|
||||||
|
return Connection->IsNetReady(Saturate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -39,7 +39,6 @@ enum class EDynamicFoundationType : uint8_t
|
|||||||
EDynamicFoundationType_MAX = 4
|
EDynamicFoundationType_MAX = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static UObject* GetPlaylistToUse()
|
static UObject* GetPlaylistToUse()
|
||||||
{
|
{
|
||||||
auto Playlist = FindObject("/Game/Athena/Playlists/Playlist_DefaultSolo.Playlist_DefaultSolo");
|
auto Playlist = FindObject("/Game/Athena/Playlists/Playlist_DefaultSolo.Playlist_DefaultSolo");
|
||||||
@@ -65,6 +64,8 @@ static UObject* GetPlaylistToUse()
|
|||||||
|
|
||||||
// SET OVERRIDE PLAYLIST DOWN HERE
|
// SET OVERRIDE PLAYLIST DOWN HERE
|
||||||
|
|
||||||
|
Playlist = FindObject("/Game/Athena/Playlists/Playlist_DefaultDuo.Playlist_DefaultDuo");
|
||||||
|
|
||||||
// Playlist = FindObject("/Game/Athena/Playlists/Playground/Playlist_Playground.Playlist_Playground");
|
// Playlist = FindObject("/Game/Athena/Playlists/Playground/Playlist_Playground.Playlist_Playground");
|
||||||
|
|
||||||
// Playlist = FindObject("/Game/Athena/Playlists/Carmine/Playlist_Carmine.Playlist_Carmine");
|
// Playlist = FindObject("/Game/Athena/Playlists/Carmine/Playlist_Carmine.Playlist_Carmine");
|
||||||
@@ -274,20 +275,23 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
|
|
||||||
GameMode->Get<int>("WarmupRequiredPlayerCount") = 1;
|
GameMode->Get<int>("WarmupRequiredPlayerCount") = 1;
|
||||||
|
|
||||||
auto PlaylistToUse = GetPlaylistToUse();
|
if (Fortnite_Version >= 3) // idk when they switched off id
|
||||||
|
{
|
||||||
|
auto PlaylistToUse = GetPlaylistToUse();
|
||||||
|
|
||||||
if (!PlaylistToUse)
|
if (!PlaylistToUse)
|
||||||
{
|
|
||||||
LOG_ERROR(LogPlaylist, "Failed to find playlist! Proceeding, but will probably not work as expected!");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Fortnite_Version >= 4)
|
|
||||||
{
|
{
|
||||||
SetPlaylist(PlaylistToUse, true);
|
LOG_ERROR(LogPlaylist, "Failed to find playlist! Proceeding, but will probably not work as expected!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Fortnite_Version >= 4)
|
||||||
|
{
|
||||||
|
SetPlaylist(PlaylistToUse, true);
|
||||||
|
|
||||||
auto CurrentPlaylist = GameState->GetCurrentPlaylist();
|
auto CurrentPlaylist = GameState->GetCurrentPlaylist();
|
||||||
LOG_INFO(LogDev, "Set playlist to {}!", CurrentPlaylist->IsValidLowLevel() ? CurrentPlaylist->GetFullName() : "Invalid");
|
LOG_INFO(LogDev, "Set playlist to {}!", CurrentPlaylist->IsValidLowLevel() ? CurrentPlaylist->GetFullName() : "Invalid");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,10 +552,13 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
GameSession->Get<int>(MaxPlayersOffset) = 100;
|
GameSession->Get<int>(MaxPlayersOffset) = 100;
|
||||||
|
|
||||||
// if (Engine_Version < 424)
|
// if (Engine_Version < 424)
|
||||||
GameState->OnRep_CurrentPlaylistInfo(); // ?
|
GameState->OnRep_CurrentPlaylistInfo(); // ?
|
||||||
|
|
||||||
// SetupNavConfig();
|
// SetupNavConfig();
|
||||||
|
|
||||||
|
static auto bAlwaysDBNOOffset = GameMode->GetOffset("bAlwaysDBNO");
|
||||||
|
GameMode->Get<bool>(bAlwaysDBNOOffset) = true;
|
||||||
|
|
||||||
LOG_INFO(LogDev, "Initialized!");
|
LOG_INFO(LogDev, "Initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -628,6 +635,7 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint
|
|||||||
CurrentTeamMembers = 0;
|
CurrentTeamMembers = 0;
|
||||||
LOG_INFO(LogTeams, "Player is going on team {} with {} members (No Playlist).", Current, CurrentTeamMembers);
|
LOG_INFO(LogTeams, "Player is going on team {} with {} members (No Playlist).", Current, CurrentTeamMembers);
|
||||||
CurrentTeamMembers++;
|
CurrentTeamMembers++;
|
||||||
|
return Current;
|
||||||
return Current++;
|
return Current++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,15 +701,15 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
|
|
||||||
bool bPrintWarmup = false;
|
bool bPrintWarmup = false;
|
||||||
|
|
||||||
if (Engine_Version != 419)
|
for (int i = 0; i < SpawnIsland_FloorLoot_Actors.Num(); i++)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SpawnIsland_FloorLoot_Actors.Num(); i++)
|
ABuildingContainer* CurrentActor = (ABuildingContainer*)SpawnIsland_FloorLoot_Actors.at(i);
|
||||||
|
|
||||||
|
// CurrentActor->K2_DestroyActor();
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
if (Engine_Version != 419)
|
||||||
{
|
{
|
||||||
ABuildingContainer* CurrentActor = (ABuildingContainer*)SpawnIsland_FloorLoot_Actors.at(i);
|
|
||||||
|
|
||||||
// CurrentActor->K2_DestroyActor();
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
auto Location = CurrentActor->GetActorLocation();
|
auto Location = CurrentActor->GetActorLocation();
|
||||||
Location.Z += UpZ;
|
Location.Z += UpZ;
|
||||||
|
|
||||||
@@ -715,11 +723,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
if (LootDrops.size())
|
if (LootDrops.size())
|
||||||
{
|
{
|
||||||
for (auto& LootDrop : LootDrops)
|
for (auto& LootDrop : LootDrops)
|
||||||
AFortPickup::SpawnPickup(LootDrop.ItemDefinition, Location, LootDrop.Count, SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop.LoadedAmmo);
|
{
|
||||||
|
auto Pickup = AFortPickup::SpawnPickup(LootDrop.ItemDefinition, Location, LootDrop.Count, SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop.LoadedAmmo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentActor->K2_DestroyActor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CurrentActor->K2_DestroyActor();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bPrint = false;
|
bool bPrint = false;
|
||||||
@@ -745,7 +755,9 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
if (LootDrops.size())
|
if (LootDrops.size())
|
||||||
{
|
{
|
||||||
for (auto& LootDrop : LootDrops)
|
for (auto& LootDrop : LootDrops)
|
||||||
AFortPickup::SpawnPickup(LootDrop.ItemDefinition, Location, LootDrop.Count, SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop.LoadedAmmo);
|
{
|
||||||
|
auto Pickup = AFortPickup::SpawnPickup(LootDrop.ItemDefinition, Location, LootDrop.Count, SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop.LoadedAmmo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CurrentActor->K2_DestroyActor();
|
CurrentActor->K2_DestroyActor();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ float UFortItemDefinition::GetMaxStackSize()
|
|||||||
{
|
{
|
||||||
static auto MaxStackSizeOffset = this->GetOffset("MaxStackSize");
|
static auto MaxStackSizeOffset = this->GetOffset("MaxStackSize");
|
||||||
|
|
||||||
bool bIsScalableFloat = Engine_Version >= 424; // idk
|
bool bIsScalableFloat = Fortnite_Version >= 12; // idk
|
||||||
|
|
||||||
if (!bIsScalableFloat)
|
if (!bIsScalableFloat)
|
||||||
return Get<int>(MaxStackSizeOffset);
|
return Get<int>(MaxStackSizeOffset);
|
||||||
|
|||||||
@@ -400,13 +400,9 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& LTDRowMap = LTD->GetRowMap();
|
auto& LTDRowMap = LTD->GetRowMap();
|
||||||
auto LTDRowMapNum = LTDRowMap.Pairs.Elements.Num();
|
|
||||||
|
|
||||||
// auto TierGroupNameStr = TierGroupName.ToString();
|
for (auto& CurrentLTD : LTDRowMap)
|
||||||
|
|
||||||
for (int i = 0; i < LTDRowMapNum; i++)
|
|
||||||
{
|
{
|
||||||
auto& CurrentLTD = LTDRowMap.Pairs.Elements[i].ElementData.Value;
|
|
||||||
auto TierData = (FFortLootTierData*)CurrentLTD.Value();
|
auto TierData = (FFortLootTierData*)CurrentLTD.Value();
|
||||||
|
|
||||||
if (IsBadReadPtr(TierData, 8)) // this shouldn't be needed
|
if (IsBadReadPtr(TierData, 8)) // this shouldn't be needed
|
||||||
@@ -516,9 +512,8 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
|
|||||||
|
|
||||||
auto& LPRowMap = LP->GetRowMap();
|
auto& LPRowMap = LP->GetRowMap();
|
||||||
|
|
||||||
for (int i = 0; i < LPRowMap.Pairs.Elements.Num(); i++)
|
for (auto& CurrentLP : LPRowMap)
|
||||||
{
|
{
|
||||||
auto& CurrentLP = LPRowMap.Pairs.Elements[i].ElementData.Value;
|
|
||||||
auto LootPackage = (FFortLootPackageData*)CurrentLP.Value();
|
auto LootPackage = (FFortLootPackageData*)CurrentLP.Value();
|
||||||
|
|
||||||
if (!LootPackage)
|
if (!LootPackage)
|
||||||
@@ -618,10 +613,8 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
|
|||||||
|
|
||||||
auto& LPRowMap = LPTables[p]->GetRowMap();
|
auto& LPRowMap = LPTables[p]->GetRowMap();
|
||||||
|
|
||||||
for (int j = 0; j < LPRowMap.Pairs.Elements.Num(); j++)
|
for (auto& CurrentLP : LPRowMap)
|
||||||
{
|
{
|
||||||
auto& CurrentLP = LPRowMap.Pairs.Elements[j].ElementData.Value;
|
|
||||||
|
|
||||||
auto LootPackage = (FFortLootPackageData*)CurrentLP.Value();
|
auto LootPackage = (FFortLootPackageData*)CurrentLP.Value();
|
||||||
|
|
||||||
if (LootPackage->GetLootPackageID().ToString() == TierGroupLPStr && LootPackage->GetWeight() != 0 && LootPackage->GetCount() != 0)
|
if (LootPackage->GetLootPackageID().ToString() == TierGroupLPStr && LootPackage->GetWeight() != 0 && LootPackage->GetCount() != 0)
|
||||||
|
|||||||
@@ -69,6 +69,12 @@ public:
|
|||||||
|
|
||||||
void TossPickup(FVector FinalLocation, class AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, EFortPickupSourceTypeFlag InPickupSourceTypeFlags, EFortPickupSpawnSource InPickupSpawnSource);
|
void TossPickup(FVector FinalLocation, class AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, EFortPickupSourceTypeFlag InPickupSourceTypeFlags, EFortPickupSpawnSource InPickupSpawnSource);
|
||||||
|
|
||||||
|
void OnRep_PrimaryPickupItemEntry()
|
||||||
|
{
|
||||||
|
static auto OnRep_PrimaryPickupItemEntryFn = FindObject<UFunction>("/Script/FortniteGame.FortPickup.OnRep_PrimaryPickupItemEntry");
|
||||||
|
this->ProcessEvent(OnRep_PrimaryPickupItemEntryFn);
|
||||||
|
}
|
||||||
|
|
||||||
FFortPickupLocationData* GetPickupLocationData()
|
FFortPickupLocationData* GetPickupLocationData()
|
||||||
{
|
{
|
||||||
static auto PickupLocationDataOffset = this->GetOffset("PickupLocationData");
|
static auto PickupLocationDataOffset = this->GetOffset("PickupLocationData");
|
||||||
|
|||||||
@@ -930,7 +930,7 @@ void AFortPlayerController::ServerEditBuildingActorHook(UObject* Context, FFrame
|
|||||||
if (!BuildingActorToEdit || !NewBuildingClass || BuildingActorToEdit->IsDestroyed() || BuildingActorToEdit->GetEditingPlayer() != PlayerState)
|
if (!BuildingActorToEdit || !NewBuildingClass || BuildingActorToEdit->IsDestroyed() || BuildingActorToEdit->GetEditingPlayer() != PlayerState)
|
||||||
{
|
{
|
||||||
LOG_INFO(LogDev, "Cheater?");
|
LOG_INFO(LogDev, "Cheater?");
|
||||||
LOG_INFO(LogDev, "BuildingActorToEdit->GetEditingPlayer(): {} PlayerState: {} NewBuildingClass: {} BuildingActorToEdit: {}", __int64(BuildingActorToEdit->GetEditingPlayer()), __int64(PlayerState), __int64(NewBuildingClass), __int64(BuildingActorToEdit));
|
LOG_INFO(LogDev, "BuildingActorToEdit->GetEditingPlayer(): {} PlayerState: {} NewBuildingClass: {} BuildingActorToEdit: {}", BuildingActorToEdit ? __int64(BuildingActorToEdit->GetEditingPlayer()) : -1, __int64(PlayerState), __int64(NewBuildingClass), __int64(BuildingActorToEdit));
|
||||||
return ServerEditBuildingActorOriginal(Context, Stack, Ret);
|
return ServerEditBuildingActorOriginal(Context, Stack, Ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,4 +116,10 @@ public:
|
|||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static UClass* StaticClass()
|
||||||
|
{
|
||||||
|
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortQuickBars");
|
||||||
|
return Class;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
@@ -15,6 +15,12 @@ public:
|
|||||||
return (float)TruncToInt(F);
|
return (float)TruncToInt(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< class T >
|
||||||
|
static constexpr FORCEINLINE T Min(const T A, const T B)
|
||||||
|
{
|
||||||
|
return (A <= B) ? A : B;
|
||||||
|
}
|
||||||
|
|
||||||
static FORCEINLINE int32 FloorToInt(float F)
|
static FORCEINLINE int32 FloorToInt(float F)
|
||||||
{
|
{
|
||||||
return TruncToInt(floorf(F));
|
return TruncToInt(floorf(F));
|
||||||
|
|||||||
@@ -22,4 +22,14 @@ bool ULevel::HasVisibilityChangeRequestPending()
|
|||||||
auto CurrentLevelPendingInvisibility = OwningWorld->Get<ULevel*>(CurrentLevelPendingInvisibilityOffset);
|
auto CurrentLevelPendingInvisibility = OwningWorld->Get<ULevel*>(CurrentLevelPendingInvisibilityOffset);
|
||||||
|
|
||||||
return this == CurrentLevelPendingVisibility || this == CurrentLevelPendingInvisibility;
|
return this == CurrentLevelPendingVisibility || this == CurrentLevelPendingInvisibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
AWorldSettings* ULevel::GetWorldSettings(bool bChecked) const
|
||||||
|
{
|
||||||
|
if (bChecked)
|
||||||
|
{
|
||||||
|
// checkf(WorldSettings != nullptr, TEXT("%s"), *GetPathName());
|
||||||
|
}
|
||||||
|
static auto WorldSettingsOffset = GetOffset("WorldSettings");
|
||||||
|
return Get<AWorldSettings*>(WorldSettingsOffset);
|
||||||
}
|
}
|
||||||
@@ -7,4 +7,5 @@ class ULevel : public UObject
|
|||||||
public:
|
public:
|
||||||
UWorld*& GetOwningWorld();
|
UWorld*& GetOwningWorld();
|
||||||
bool HasVisibilityChangeRequestPending();
|
bool HasVisibilityChangeRequestPending();
|
||||||
|
AWorldSettings* GetWorldSettings(bool bChecked = true) const;
|
||||||
};
|
};
|
||||||
@@ -133,6 +133,8 @@ public:
|
|||||||
return Pair.Value();
|
return Pair.Value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_INFO(LogDev, "Failed to find Key!!!");
|
||||||
}
|
}
|
||||||
FORCEINLINE ValueType& Find(const KeyType& Key)
|
FORCEINLINE ValueType& Find(const KeyType& Key)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,6 +27,19 @@ public:
|
|||||||
return Get<AActor*>(ViewTargetOffset);
|
return Get<AActor*>(ViewTargetOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 IsNetReady(bool Saturate)
|
||||||
|
{
|
||||||
|
static auto IsNetReadyOffset = 0x298; // 1.11
|
||||||
|
int32 (*IsNetReadyOriginal)(UNetConnection* Connection, bool Saturate) = decltype(IsNetReadyOriginal)(this->VFTable[IsNetReadyOffset / 8]);
|
||||||
|
return IsNetReadyOriginal(this, Saturate);
|
||||||
|
}
|
||||||
|
|
||||||
|
double& GetLastReceiveTime()
|
||||||
|
{
|
||||||
|
static auto LastReceiveTimeOffset = GetOffset("LastReceiveTime");
|
||||||
|
return Get<double>(LastReceiveTimeOffset);
|
||||||
|
}
|
||||||
|
|
||||||
TSet<FName>& GetClientVisibleLevelNames()
|
TSet<FName>& GetClientVisibleLevelNames()
|
||||||
{
|
{
|
||||||
static auto ClientVisibleLevelNamesOffset = 0x336C8;
|
static auto ClientVisibleLevelNamesOffset = 0x336C8;
|
||||||
@@ -59,7 +72,7 @@ public:
|
|||||||
|
|
||||||
bool ClientHasInitializedLevelFor(const AActor* TestActor) const
|
bool ClientHasInitializedLevelFor(const AActor* TestActor) const
|
||||||
{
|
{
|
||||||
bool (*ClientHasInitializedLevelForOriginal)(const UNetConnection* Connection, const AActor * TestActor) = decltype(ClientHasInitializedLevelForOriginal)(this->VFTable[0x300 / 8]);
|
bool (*ClientHasInitializedLevelForOriginal)(const UNetConnection* Connection, const AActor* TestActor) = decltype(ClientHasInitializedLevelForOriginal)(this->VFTable[0x300 / 8]);
|
||||||
return ClientHasInitializedLevelForOriginal(this, TestActor);
|
return ClientHasInitializedLevelForOriginal(this, TestActor);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -11,6 +11,69 @@
|
|||||||
#include "ActorChannel.h"
|
#include "ActorChannel.h"
|
||||||
#include "KismetSystemLibrary.h"
|
#include "KismetSystemLibrary.h"
|
||||||
#include "UnrealMathUtility.h"
|
#include "UnrealMathUtility.h"
|
||||||
|
#include "FortQuickBars.h"
|
||||||
|
|
||||||
|
void UNetDriver::TickFlushHook(UNetDriver* NetDriver)
|
||||||
|
{
|
||||||
|
static auto ReplicationDriverOffset = NetDriver->GetOffset("ReplicationDriver", false);
|
||||||
|
|
||||||
|
if (ReplicationDriverOffset == -1)
|
||||||
|
{
|
||||||
|
NetDriver->ServerReplicateActors();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (auto ReplicationDriver = NetDriver->Get(ReplicationDriverOffset))
|
||||||
|
reinterpret_cast<void(*)(UObject*)>(ReplicationDriver->VFTable[Offsets::ServerReplicateActors])(ReplicationDriver);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TickFlushOriginal(NetDriver);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Test3(AActor* Actor, const std::string& Str)
|
||||||
|
{
|
||||||
|
if (Actor->IsA(AFortPawn::StaticClass()))
|
||||||
|
{
|
||||||
|
LOG_INFO(LogDev, "[{}] Pawn", Str)
|
||||||
|
}
|
||||||
|
if (Actor->IsA(AFortQuickBars::StaticClass()))
|
||||||
|
{
|
||||||
|
LOG_INFO(LogDev, "[{}] QuickBars", Str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NAME_None 0
|
||||||
|
|
||||||
|
static FNetViewer ConstructNetViewer(UNetConnection* NetConnection)
|
||||||
|
{
|
||||||
|
FNetViewer newViewer{};
|
||||||
|
newViewer.Connection = NetConnection;
|
||||||
|
newViewer.InViewer = NetConnection->GetPlayerController() ? NetConnection->GetPlayerController() : NetConnection->GetOwningActor();
|
||||||
|
newViewer.ViewTarget = NetConnection->GetViewTarget();
|
||||||
|
|
||||||
|
// if (!NetConnection->GetOwningActor() || !(!NetConnection->GetPlayerController() || (NetConnection->GetPlayerController() == NetConnection->GetOwningActor())))
|
||||||
|
// return newViewer;
|
||||||
|
|
||||||
|
APlayerController* ViewingController = NetConnection->GetPlayerController();
|
||||||
|
|
||||||
|
newViewer.ViewLocation = newViewer.ViewTarget->GetActorLocation();
|
||||||
|
|
||||||
|
if (ViewingController)
|
||||||
|
{
|
||||||
|
static auto ControlRotationOffset = ViewingController->GetOffset("ControlRotation");
|
||||||
|
FRotator ViewRotation = ViewingController->Get<FRotator>(ControlRotationOffset); // hmmmm // ViewingController->GetControlRotation();
|
||||||
|
// AFortPlayerControllerAthena::GetPlayerViewPointHook(Cast<AFortPlayerControllerAthena>(ViewingController, false), newViewer.ViewLocation, ViewRotation);
|
||||||
|
// ViewingController->GetActorEyesViewPoint(&newViewer.ViewLocation, &ViewRotation); // HMMM
|
||||||
|
|
||||||
|
static auto GetActorEyesViewPointOffset = 0x5B0;
|
||||||
|
void (*GetActorEyesViewPointOriginal)(AController*, FVector * a2, FRotator * a3) = decltype(GetActorEyesViewPointOriginal)(ViewingController->VFTable[GetActorEyesViewPointOffset / 8]);
|
||||||
|
GetActorEyesViewPointOriginal(ViewingController, &newViewer.ViewLocation, &ViewRotation);
|
||||||
|
|
||||||
|
newViewer.ViewDir = ViewRotation.Vector();
|
||||||
|
}
|
||||||
|
|
||||||
|
return newViewer;
|
||||||
|
}
|
||||||
|
|
||||||
FNetworkObjectList& UNetDriver::GetNetworkObjectList()
|
FNetworkObjectList& UNetDriver::GetNetworkObjectList()
|
||||||
{
|
{
|
||||||
@@ -31,6 +94,58 @@ struct FPacketIdRange
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
float GetTimeSecondsForWorld(UWorld* World)
|
||||||
|
{
|
||||||
|
static auto TimeSecondsOffset = 0x900;
|
||||||
|
return *(float*)(__int64(World) + TimeSecondsOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetChannelActorForDestroy(UActorChannel* ActorChannel, FActorDestructionInfo* DestructInfo)
|
||||||
|
{
|
||||||
|
static auto ConnectionOffset = ActorChannel->GetOffset("Connection");
|
||||||
|
UNetConnection* Connection = ActorChannel->Get<UNetConnection*>(ConnectionOffset);
|
||||||
|
|
||||||
|
auto State = *(uint8_t*)(__int64(Connection) + 0x12C);
|
||||||
|
|
||||||
|
if (!(State - 2 <= 1)) // this will make sure that it is USOCK_Open or USOCK_Pending
|
||||||
|
return;
|
||||||
|
|
||||||
|
using FOutBunch = __int64;
|
||||||
|
|
||||||
|
static auto PackageMapOffset = Connection->GetOffset("PackageMap");
|
||||||
|
auto PackageMap = Connection->Get(PackageMapOffset);
|
||||||
|
|
||||||
|
FOutBunch* CloseBunch = Alloc(0x200);
|
||||||
|
|
||||||
|
if (!CloseBunch)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static FOutBunch(*FOutBunchConstructor)(FOutBunch * a1, UActorChannel * a2, bool bInClose) = decltype(FOutBunchConstructor)(__int64(GetModuleHandleW(0)) + 0x194E800);
|
||||||
|
FPacketIdRange Range(0);
|
||||||
|
FPacketIdRange* (*SendBunchOriginal)(UActorChannel * Channel, FPacketIdRange * OutRange, FOutBunch * Bunch, bool Merge) = decltype(SendBunchOriginal)(ActorChannel->VFTable[0x288 / 8]);
|
||||||
|
bool (*UPackageMap_WriteObjectOriginal)(UObject * PackageMap, FOutBunch * Ar, UObject * InOuter, FNetworkGUID NetGUID, FString ObjectName) = decltype(UPackageMap_WriteObjectOriginal)(PackageMap->VFTable[0x238 / 8]);
|
||||||
|
static void (*FArchiveDeconstructor)(FOutBunch * Ar) = decltype(FArchiveDeconstructor)(__int64(GetModuleHandleW(0)) + 0xC36500);
|
||||||
|
|
||||||
|
FOutBunchConstructor(CloseBunch, ActorChannel, true);
|
||||||
|
|
||||||
|
// we could set bDormant but it's set by default to 0.
|
||||||
|
SetBitfield((PlaceholderBitfield*)(__int64(CloseBunch) + 0x30), 4, true); // bReliable
|
||||||
|
|
||||||
|
/* LOG_INFO(LogDev, "UPackageMap_WriteObjectOriginal: 0x{:x}", __int64(UPackageMap_WriteObjectOriginal) - __int64(GetModuleHandleW(0)));
|
||||||
|
LOG_INFO(LogDev, "DestructInfo->PathName: {} Num: {} Max: {} Data: {}", DestructInfo->PathName.ToString(), DestructInfo->PathName.Data.Num(), DestructInfo->PathName.Data.ArrayMax, __int64(DestructInfo->PathName.Data.Data));
|
||||||
|
// LOG_INFO(LogDev, "DestructInfo->ObjOuter: {}", DestructInfo->ObjOuter.Get()->IsValidLowLevel() ? DestructInfo->ObjOuter.Get()->GetFullName() : "BadRead");
|
||||||
|
|
||||||
|
if (DestructInfo->PathName.ToString() == "???")
|
||||||
|
return; */
|
||||||
|
|
||||||
|
UPackageMap_WriteObjectOriginal(PackageMap, CloseBunch, DestructInfo->ObjOuter.Get(), DestructInfo->NetGUID, DestructInfo->PathName);
|
||||||
|
SendBunchOriginal(ActorChannel, &Range, CloseBunch, false);
|
||||||
|
|
||||||
|
FArchiveDeconstructor(CloseBunch);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CVarSetNetDormancyEnabled = 1; // idk what we supposed to set this to
|
||||||
|
|
||||||
#define CLOSEPROXIMITY 500.f
|
#define CLOSEPROXIMITY 500.f
|
||||||
#define NEARSIGHTTHRESHOLD 2000.f
|
#define NEARSIGHTTHRESHOLD 2000.f
|
||||||
#define MEDSIGHTTHRESHOLD 3162.f
|
#define MEDSIGHTTHRESHOLD 3162.f
|
||||||
@@ -84,43 +199,6 @@ FActorPriority::FActorPriority(UNetConnection* InConnection, FActorDestructionIn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetChannelActorForDestroy(UActorChannel* ActorChannel, FActorDestructionInfo* DestructInfo)
|
|
||||||
{
|
|
||||||
static auto ConnectionOffset = ActorChannel->GetOffset("Connection");
|
|
||||||
UNetConnection* Connection = ActorChannel->Get<UNetConnection*>(ConnectionOffset);
|
|
||||||
|
|
||||||
auto State = *(uint8_t*)(__int64(Connection) + 0x12C);
|
|
||||||
|
|
||||||
if (!(State - 2 <= 1)) // this will make sure that it is USOCK_Open or USOCK_Pending
|
|
||||||
return;
|
|
||||||
|
|
||||||
using FOutBunch = __int64;
|
|
||||||
|
|
||||||
static auto PackageMapOffset = Connection->GetOffset("PackageMap");
|
|
||||||
auto PackageMap = Connection->Get(PackageMapOffset);
|
|
||||||
|
|
||||||
FOutBunch* CloseBunch = Alloc(0x200);
|
|
||||||
|
|
||||||
if (!CloseBunch)
|
|
||||||
return;
|
|
||||||
|
|
||||||
static FOutBunch(*FOutBunchConstructor)(FOutBunch* a1, UActorChannel* a2, bool bInClose) = decltype(FOutBunchConstructor)(__int64(GetModuleHandleW(0)) + 0x194E800);
|
|
||||||
/* *CloseBunch = */ FOutBunchConstructor(CloseBunch, ActorChannel, true);
|
|
||||||
|
|
||||||
// we could set bDormant but it's set by default to 0.
|
|
||||||
|
|
||||||
SetBitfield((PlaceholderBitfield*)(__int64(CloseBunch) + 0x30), 4, true); // bReliable
|
|
||||||
|
|
||||||
bool (*UPackageMap_WriteObjectOriginal)(UObject* PackageMap, FOutBunch* Ar, UObject* InOuter, FNetworkGUID NetGUID, FString ObjectName) = decltype(UPackageMap_WriteObjectOriginal)(PackageMap->VFTable[0x238 / 8]);
|
|
||||||
UPackageMap_WriteObjectOriginal(PackageMap, CloseBunch, DestructInfo->ObjOuter.Get(), DestructInfo->NetGUID, DestructInfo->PathName);
|
|
||||||
|
|
||||||
FPacketIdRange (*SendBunchOriginal)(UActorChannel* Channel, FOutBunch* Bunch, bool Merge) = decltype(SendBunchOriginal)(ActorChannel->VFTable[0x288 / 8]);
|
|
||||||
SendBunchOriginal(ActorChannel, CloseBunch, false);
|
|
||||||
|
|
||||||
static void (*FArchiveDeconstructor)(FOutBunch* Ar) = decltype(FArchiveDeconstructor)(__int64(GetModuleHandleW(0)) + 0xC36500);
|
|
||||||
FArchiveDeconstructor(CloseBunch);
|
|
||||||
}
|
|
||||||
|
|
||||||
TSet<FNetworkGUID>& GetConnectionDestroyedStartupOrDormantActors(UNetConnection* Connection)
|
TSet<FNetworkGUID>& GetConnectionDestroyedStartupOrDormantActors(UNetConnection* Connection)
|
||||||
{
|
{
|
||||||
return *(TSet<FNetworkGUID>*)(__int64(Connection) + 0x33678);
|
return *(TSet<FNetworkGUID>*)(__int64(Connection) + 0x33678);
|
||||||
@@ -140,22 +218,7 @@ void UNetDriver::RemoveNetworkActor(AActor* Actor)
|
|||||||
// RenamedStartupActors.Remove(Actor->GetFName());
|
// RenamedStartupActors.Remove(Actor->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UNetDriver::TickFlushHook(UNetDriver* NetDriver)
|
int MaxConnectionsToTickPerServerFrame = 25;
|
||||||
{
|
|
||||||
static auto ReplicationDriverOffset = NetDriver->GetOffset("ReplicationDriver", false);
|
|
||||||
|
|
||||||
if (ReplicationDriverOffset == -1)
|
|
||||||
{
|
|
||||||
NetDriver->ServerReplicateActors();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (auto ReplicationDriver = NetDriver->Get(ReplicationDriverOffset))
|
|
||||||
reinterpret_cast<void(*)(UObject*)>(ReplicationDriver->VFTable[Offsets::ServerReplicateActors])(ReplicationDriver);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TickFlushOriginal(NetDriver);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 ServerReplicateActors_PrepConnections(UNetDriver* NetDriver)
|
int32 ServerReplicateActors_PrepConnections(UNetDriver* NetDriver)
|
||||||
{
|
{
|
||||||
@@ -163,6 +226,9 @@ int32 ServerReplicateActors_PrepConnections(UNetDriver* NetDriver)
|
|||||||
|
|
||||||
int32 NumClientsToTick = ClientConnections.Num();
|
int32 NumClientsToTick = ClientConnections.Num();
|
||||||
|
|
||||||
|
if (MaxConnectionsToTickPerServerFrame > 0)
|
||||||
|
NumClientsToTick = FMath::Min(ClientConnections.Num(), MaxConnectionsToTickPerServerFrame);
|
||||||
|
|
||||||
bool bFoundReadyConnection = false;
|
bool bFoundReadyConnection = false;
|
||||||
|
|
||||||
for (int32 ConnIdx = 0; ConnIdx < ClientConnections.Num(); ConnIdx++)
|
for (int32 ConnIdx = 0; ConnIdx < ClientConnections.Num(); ConnIdx++)
|
||||||
@@ -174,8 +240,10 @@ int32 ServerReplicateActors_PrepConnections(UNetDriver* NetDriver)
|
|||||||
|
|
||||||
AActor* OwningActor = Connection->GetOwningActor();
|
AActor* OwningActor = Connection->GetOwningActor();
|
||||||
|
|
||||||
if (OwningActor != NULL) // && /* Connection->State == USOCK_Open && */ (Connection->Driver->Time - Connection->LastReceiveTime < 1.5f))
|
if (OwningActor != NULL && /* Connection->State == USOCK_Open && */ (Connection->GetDriver()->GetTime() - Connection->GetLastReceiveTime() < 1.5f))
|
||||||
{
|
{
|
||||||
|
// check( World == OwningActor->GetWorld() );
|
||||||
|
|
||||||
bFoundReadyConnection = true;
|
bFoundReadyConnection = true;
|
||||||
|
|
||||||
AActor* DesiredViewTarget = OwningActor;
|
AActor* DesiredViewTarget = OwningActor;
|
||||||
@@ -211,15 +279,9 @@ enum class ENetRole : uint8_t
|
|||||||
FORCEINLINE float FRand()
|
FORCEINLINE float FRand()
|
||||||
{
|
{
|
||||||
return ReplicationRandStream.FRand();
|
return ReplicationRandStream.FRand();
|
||||||
|
|
||||||
std::random_device rd;
|
|
||||||
std::mt19937 gen(rd());
|
|
||||||
std::uniform_real_distribution<> dis(0, 1);
|
|
||||||
float random_number = dis(gen);
|
|
||||||
|
|
||||||
return random_number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 1 // below is "proper"
|
||||||
FORCEINLINE float SRand()
|
FORCEINLINE float SRand()
|
||||||
{
|
{
|
||||||
GSRandSeed = (GSRandSeed * 196314165) + 907633515;
|
GSRandSeed = (GSRandSeed * 196314165) + 907633515;
|
||||||
@@ -233,29 +295,36 @@ FORCEINLINE float SRand()
|
|||||||
// res /= 3;
|
// res /= 3;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
FORCEINLINE float SRand()
|
||||||
|
{
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
|
||||||
|
auto value = now_ms.time_since_epoch().count();
|
||||||
|
|
||||||
void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList)
|
std::default_random_engine generator(value);
|
||||||
|
|
||||||
|
std::uniform_real_distribution<float> distribution(0.0f, 1.0f);
|
||||||
|
return distribution(generator);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList, const float ServerTickTime)
|
||||||
{
|
{
|
||||||
std::vector<AActor*> ActorsToRemove;
|
std::vector<AActor*> ActorsToRemove;
|
||||||
|
|
||||||
auto& ActiveObjects = GetNetworkObjectList().ActiveNetworkObjects;
|
|
||||||
|
|
||||||
auto World = GetWorld();
|
auto World = GetWorld();
|
||||||
|
|
||||||
for (const TSharedPtr<FNetworkObjectInfo>& ActorInfo : ActiveObjects)
|
for (const TSharedPtr<FNetworkObjectInfo>& ActorInfo : GetNetworkObjectList().ActiveNetworkObjects)
|
||||||
{
|
{
|
||||||
if (!ActorInfo->bPendingNetUpdate && UGameplayStatics::GetTimeSeconds(GetWorld()) <= ActorInfo->NextUpdateTime)
|
if (!ActorInfo->bPendingNetUpdate && GetTimeSecondsForWorld(GetWorld()) <= ActorInfo->NextUpdateTime)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Actor = ActorInfo->Actor;
|
auto Actor = ActorInfo->Actor;
|
||||||
|
|
||||||
if (!Actor)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Actor->IsPendingKillPending())
|
if (Actor->IsPendingKillPending())
|
||||||
// if (Actor->IsPendingKill())
|
|
||||||
{
|
{
|
||||||
ActorsToRemove.push_back(Actor);
|
ActorsToRemove.push_back(Actor);
|
||||||
continue;
|
continue;
|
||||||
@@ -275,39 +344,40 @@ void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObj
|
|||||||
|
|
||||||
// We should check the level stuff here.
|
// We should check the level stuff here.
|
||||||
|
|
||||||
if (Actor->GetNetDormancy() == ENetDormancy::DORM_Initial && Actor->IsNetStartupActor()) // IsDormInitialStartupActor
|
if (Actor->GetNetDormancy() == ENetDormancy::DORM_Initial && Actor->IsNetStartupActor())
|
||||||
{
|
{
|
||||||
ActorsToRemove.push_back(Actor);
|
ActorsToRemove.push_back(Actor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We should check NeedsLoadForClient here.
|
static auto NeedsLoadForClientOriginalOffset = 0xD0;
|
||||||
// We should make sure the actor is in the same world here but I don't believe it is needed.
|
bool (*NeedsLoadForClientOriginal)(AActor* Actor) = decltype(NeedsLoadForClientOriginal)(Actor->VFTable[NeedsLoadForClientOriginalOffset / 8]);
|
||||||
|
|
||||||
auto TimeSeconds = UGameplayStatics::GetTimeSeconds(World); // Can we do this outside of the loop?
|
if (!NeedsLoadForClientOriginal(Actor)) // Should we remove?
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// We should make sure the actor is in the same world here but I don't believe it is needed.
|
||||||
|
|
||||||
if (ActorInfo->LastNetReplicateTime == 0)
|
if (ActorInfo->LastNetReplicateTime == 0)
|
||||||
{
|
{
|
||||||
ActorInfo->LastNetReplicateTime = UGameplayStatics::GetTimeSeconds(World);
|
ActorInfo->LastNetReplicateTime = GetTimeSecondsForWorld(World);
|
||||||
ActorInfo->OptimalNetUpdateDelta = 1.0f / Actor->GetNetUpdateFrequency();
|
ActorInfo->OptimalNetUpdateDelta = 1.0f / Actor->GetNetUpdateFrequency();
|
||||||
}
|
}
|
||||||
|
|
||||||
const float ScaleDownStartTime = 2.0f;
|
const float ScaleDownStartTime = 2.0f;
|
||||||
const float ScaleDownTimeRange = 5.0f;
|
const float ScaleDownTimeRange = 5.0f;
|
||||||
|
|
||||||
const float LastReplicateDelta = TimeSeconds - ActorInfo->LastNetReplicateTime;
|
const float LastReplicateDelta = GetTimeSecondsForWorld(World) - ActorInfo->LastNetReplicateTime;
|
||||||
|
|
||||||
if (LastReplicateDelta > ScaleDownStartTime)
|
if (LastReplicateDelta > ScaleDownStartTime)
|
||||||
{
|
{
|
||||||
static auto MinNetUpdateFrequencyOffset = Actor->GetOffset("MinNetUpdateFrequency");
|
if (Actor->GetMinNetUpdateFrequency() == 0.0f)
|
||||||
|
|
||||||
if (Actor->Get<float>(MinNetUpdateFrequencyOffset) == 0.0f)
|
|
||||||
{
|
{
|
||||||
Actor->Get<float>(MinNetUpdateFrequencyOffset) = 2.0f;
|
Actor->GetMinNetUpdateFrequency() = 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency(); // Don't go faster than NetUpdateFrequency
|
const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency(); // Don't go faster than NetUpdateFrequency
|
||||||
const float MaxOptimalDelta = FMath::Max(1.0f / Actor->GetNetUpdateFrequency(), MinOptimalDelta); // Don't go slower than MinNetUpdateFrequency (or NetUpdateFrequency if it's slower)
|
const float MaxOptimalDelta = FMath::Max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta); // Don't go slower than MinNetUpdateFrequency (or NetUpdateFrequency if it's slower)
|
||||||
|
|
||||||
const float Alpha = FMath::Clamp( (LastReplicateDelta - ScaleDownStartTime) / ScaleDownTimeRange, 0.0f, 1.0f);
|
const float Alpha = FMath::Clamp( (LastReplicateDelta - ScaleDownStartTime) / ScaleDownTimeRange, 0.0f, 1.0f);
|
||||||
ActorInfo->OptimalNetUpdateDelta = FMath::Lerp(MinOptimalDelta, MaxOptimalDelta, Alpha);
|
ActorInfo->OptimalNetUpdateDelta = FMath::Lerp(MinOptimalDelta, MaxOptimalDelta, Alpha);
|
||||||
@@ -319,13 +389,13 @@ void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObj
|
|||||||
const float NextUpdateDelta = bUseAdapativeNetFrequency ? ActorInfo->OptimalNetUpdateDelta : 1.0f / Actor->GetNetUpdateFrequency();
|
const float NextUpdateDelta = bUseAdapativeNetFrequency ? ActorInfo->OptimalNetUpdateDelta : 1.0f / Actor->GetNetUpdateFrequency();
|
||||||
|
|
||||||
// then set the next update time
|
// then set the next update time
|
||||||
float ServerTickTime = 1.f / 30;
|
ActorInfo->NextUpdateTime = GetTimeSecondsForWorld(World) + SRand() * ServerTickTime + NextUpdateDelta;
|
||||||
ActorInfo->NextUpdateTime = TimeSeconds + SRand() * ServerTickTime + NextUpdateDelta;
|
|
||||||
ActorInfo->LastNetUpdateTime = GetTime();
|
ActorInfo->LastNetUpdateTime = GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
ActorInfo->bPendingNetUpdate = false;
|
ActorInfo->bPendingNetUpdate = false;
|
||||||
|
|
||||||
|
// ensure( OutConsiderList.Num() < OutConsiderList.Max() );
|
||||||
OutConsiderList.push_back(ActorInfo.Get());
|
OutConsiderList.push_back(ActorInfo.Get());
|
||||||
|
|
||||||
static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication);
|
static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication);
|
||||||
@@ -446,6 +516,61 @@ static FORCEINLINE bool ShouldActorGoDormant(AActor* Actor, const std::vector<FN
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UActorChannel* FindChannel(UNetConnection* Connection, FNetworkObjectInfo* ActorInfo)
|
||||||
|
{
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
auto& ActorChannels = Connection->GetActorChannels();
|
||||||
|
|
||||||
|
for (auto& Pair : ActorChannels)
|
||||||
|
{
|
||||||
|
if (Pair.First == ActorInfo->WeakActor)
|
||||||
|
{
|
||||||
|
return Pair.Second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Actor = ActorInfo->Actor;
|
||||||
|
|
||||||
|
if (!Actor)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
static auto OpenChannelsOffset = Connection->GetOffset("OpenChannels");
|
||||||
|
auto& OpenChannels = Connection->Get<TArray<UChannel*>>(OpenChannelsOffset);
|
||||||
|
|
||||||
|
static auto ActorChannelClass = FindObject<UClass>("/Script/Engine.ActorChannel");
|
||||||
|
|
||||||
|
// LOG_INFO(LogReplication, "OpenChannels.Num(): {}", OpenChannels.Num());
|
||||||
|
|
||||||
|
for (int i = 0; i < OpenChannels.Num(); i++)
|
||||||
|
{
|
||||||
|
auto Channel = OpenChannels.at(i);
|
||||||
|
|
||||||
|
if (!Channel)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// LOG_INFO(LogReplication, "[{}] Class {}", i, Channel->ClassPrivate ? Channel->ClassPrivate->GetFullName() : "InvalidObject");
|
||||||
|
|
||||||
|
// if (!Channel->IsA(ActorChannelClass))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
if (Channel->ClassPrivate != ActorChannelClass)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
static auto ActorOffset = Channel->GetOffset("Actor");
|
||||||
|
|
||||||
|
if (Channel->Get<AActor*>(ActorOffset) != Actor)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return (UActorChannel*)Channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, const std::vector<FNetworkObjectInfo*> ConsiderList, const bool bCPUSaturated, FActorPriority*& OutPriorityList, FActorPriority**& OutPriorityActors)
|
int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, const std::vector<FNetworkObjectInfo*> ConsiderList, const bool bCPUSaturated, FActorPriority*& OutPriorityList, FActorPriority**& OutPriorityActors)
|
||||||
{
|
{
|
||||||
GetNetTag()++;
|
GetNetTag()++;
|
||||||
@@ -472,8 +597,8 @@ int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connect
|
|||||||
|
|
||||||
if (MaxSortedActors > 0)
|
if (MaxSortedActors > 0)
|
||||||
{
|
{
|
||||||
OutPriorityList = Alloc<FActorPriority>(MaxSortedActors * sizeof(FActorPriority));
|
OutPriorityList = (FActorPriority*)FMemory::Realloc(nullptr, MaxSortedActors * sizeof(FActorPriority), 0); // Alloc<FActorPriority>(MaxSortedActors * sizeof(FActorPriority));
|
||||||
OutPriorityActors = Alloc<FActorPriority*>(MaxSortedActors * sizeof(FActorPriority*));
|
OutPriorityActors = (FActorPriority**)FMemory::Realloc(nullptr, MaxSortedActors * sizeof(FActorPriority*), 0);// Alloc<FActorPriority*>(MaxSortedActors * sizeof(FActorPriority*));
|
||||||
|
|
||||||
// check( World == Connection->ViewTarget->GetWorld() );
|
// check( World == Connection->ViewTarget->GetWorld() );
|
||||||
|
|
||||||
@@ -485,19 +610,7 @@ int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connect
|
|||||||
FNetworkObjectInfo* ActorInfo = ConsiderList.at(i);
|
FNetworkObjectInfo* ActorInfo = ConsiderList.at(i);
|
||||||
AActor* Actor = ActorInfo->Actor;
|
AActor* Actor = ActorInfo->Actor;
|
||||||
|
|
||||||
auto& ActorChannels = Connection->GetActorChannels();
|
UActorChannel* Channel = FindChannel(Connection, ActorInfo);
|
||||||
UActorChannel* Channel = nullptr;
|
|
||||||
|
|
||||||
// Connection->ActorChannels.FindRef(ActorInfo->WeakActor);
|
|
||||||
|
|
||||||
for (int i = 0; i < ActorChannels.Pairs.Num(); i++)
|
|
||||||
{
|
|
||||||
if (ActorChannels.Pairs[i].First == ActorInfo->WeakActor)
|
|
||||||
{
|
|
||||||
Channel = ActorChannels.Pairs[i].Second;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Channel)
|
if (!Channel)
|
||||||
{
|
{
|
||||||
@@ -509,8 +622,6 @@ int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connect
|
|||||||
|
|
||||||
if (!IsActorRelevantToConnection(Actor, ConnectionViewers))
|
if (!IsActorRelevantToConnection(Actor, ConnectionViewers))
|
||||||
{
|
{
|
||||||
// LOG_INFO(LogDev, "Not relevant!");
|
|
||||||
|
|
||||||
// If not relevant (and we don't have a channel), skip
|
// If not relevant (and we don't have a channel), skip
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -537,13 +648,11 @@ int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connect
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else if (CVarSetNetDormancyEnabled.GetValueOnGameThread() != 0)
|
else if (CVarSetNetDormancyEnabled != 0)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Skip Actor if dormant
|
// Skip Actor if dormant
|
||||||
if (IsActorDormant(ActorInfo, WeakConnection))
|
if (IsActorDormant(ActorInfo, WeakConnection))
|
||||||
{
|
{
|
||||||
// LOG_INFO(LogDev, "Actor is dormant!");
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,23 +677,20 @@ int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connect
|
|||||||
OutPriorityActors[FinalSortedCount] = OutPriorityList + FinalSortedCount;
|
OutPriorityActors[FinalSortedCount] = OutPriorityList + FinalSortedCount;
|
||||||
|
|
||||||
FinalSortedCount++;
|
FinalSortedCount++;
|
||||||
|
// Test3(Actor, "ryo i got added");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add in deleted actors
|
// Add in deleted actors
|
||||||
|
|
||||||
/*
|
/* for (auto& CurrentGuid : Connection_DestroyedStartupOrDormantActors)
|
||||||
|
|
||||||
for (auto& CurrentGuid : Connection_DestroyedStartupOrDormantActors)
|
|
||||||
{
|
{
|
||||||
FActorDestructionInfo& DInfo = GetDriverDestroyedStartupOrDormantActors(this).Find(CurrentGuid);
|
FActorDestructionInfo& DInfo = GetDriverDestroyedStartupOrDormantActors(this).Find(CurrentGuid);
|
||||||
OutPriorityList[FinalSortedCount] = FActorPriority(Connection, &DInfo, ConnectionViewers);
|
OutPriorityList[FinalSortedCount] = FActorPriority(Connection, &DInfo, ConnectionViewers);
|
||||||
OutPriorityActors[FinalSortedCount] = OutPriorityList + FinalSortedCount;
|
OutPriorityActors[FinalSortedCount] = OutPriorityList + FinalSortedCount;
|
||||||
FinalSortedCount++;
|
FinalSortedCount++;
|
||||||
DeletedCount++;
|
DeletedCount++;
|
||||||
}
|
} */
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Sort(OutPriorityActors, FinalSortedCount, FCompareFActorPriority());
|
// Sort(OutPriorityActors, FinalSortedCount, FCompareFActorPriority());
|
||||||
}
|
}
|
||||||
@@ -592,32 +698,6 @@ int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connect
|
|||||||
return FinalSortedCount;
|
return FinalSortedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NAME_None 0
|
|
||||||
|
|
||||||
static FNetViewer ConstructNetViewer(UNetConnection* NetConnection)
|
|
||||||
{
|
|
||||||
FNetViewer newViewer{};
|
|
||||||
newViewer.Connection = NetConnection;
|
|
||||||
newViewer.InViewer = NetConnection->GetPlayerController() ? NetConnection->GetPlayerController() : NetConnection->GetOwningActor();
|
|
||||||
newViewer.ViewTarget = NetConnection->GetViewTarget();
|
|
||||||
|
|
||||||
if (!NetConnection->GetOwningActor() || !(!NetConnection->GetPlayerController() || (NetConnection->GetPlayerController() == NetConnection->GetOwningActor())))
|
|
||||||
return newViewer;
|
|
||||||
|
|
||||||
APlayerController* ViewingController = NetConnection->GetPlayerController();
|
|
||||||
|
|
||||||
newViewer.ViewLocation = newViewer.ViewTarget->GetActorLocation();
|
|
||||||
|
|
||||||
if (ViewingController)
|
|
||||||
{
|
|
||||||
FRotator ViewRotation = ViewingController->GetControlRotation();
|
|
||||||
AFortPlayerControllerAthena::GetPlayerViewPointHook(Cast<AFortPlayerControllerAthena>(ViewingController, false), newViewer.ViewLocation, ViewRotation);
|
|
||||||
newViewer.ViewDir = ViewRotation.Vector();
|
|
||||||
}
|
|
||||||
|
|
||||||
return newViewer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, FActorPriority** PriorityActors, const int32 FinalSortedCount, int32& OutUpdated)
|
int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, FActorPriority** PriorityActors, const int32 FinalSortedCount, int32& OutUpdated)
|
||||||
{
|
{
|
||||||
static UChannel* (*CreateChannel)(UNetConnection*, int, bool, int32_t) = decltype(CreateChannel)(Addresses::CreateChannel);
|
static UChannel* (*CreateChannel)(UNetConnection*, int, bool, int32_t) = decltype(CreateChannel)(Addresses::CreateChannel);
|
||||||
@@ -628,6 +708,11 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
|||||||
int32 ActorUpdatesThisConnectionSent = 0;
|
int32 ActorUpdatesThisConnectionSent = 0;
|
||||||
int32 FinalRelevantCount = 0;
|
int32 FinalRelevantCount = 0;
|
||||||
|
|
||||||
|
if (!Connection->IsNetReady(0))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (int32 j = 0; j < FinalSortedCount; j++)
|
for (int32 j = 0; j < FinalSortedCount; j++)
|
||||||
{
|
{
|
||||||
FNetworkObjectInfo* ActorInfo = PriorityActors[j]->ActorInfo;
|
FNetworkObjectInfo* ActorInfo = PriorityActors[j]->ActorInfo;
|
||||||
@@ -642,14 +727,30 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& Connection_DestroyedStartupOrDormantActors = GetConnectionDestroyedStartupOrDormantActors(Connection);
|
||||||
|
|
||||||
|
bool bFound = false;
|
||||||
|
|
||||||
|
for (auto& aa : Connection_DestroyedStartupOrDormantActors)
|
||||||
|
{
|
||||||
|
if (aa == PriorityActors[j]->DestructionInfo->NetGUID)
|
||||||
|
{
|
||||||
|
bFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO(LogDev, "bFound: {}", bFound);
|
||||||
|
|
||||||
|
if (!bFound)
|
||||||
|
continue;
|
||||||
|
|
||||||
UActorChannel* Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1);
|
UActorChannel* Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1);
|
||||||
|
|
||||||
if (Channel)
|
if (Channel)
|
||||||
{
|
{
|
||||||
FinalRelevantCount++;
|
FinalRelevantCount++;
|
||||||
|
|
||||||
auto& Connection_DestroyedStartupOrDormantActors = GetConnectionDestroyedStartupOrDormantActors(Connection);
|
|
||||||
|
|
||||||
SetChannelActorForDestroy(Channel, PriorityActors[j]->DestructionInfo); // Send a close bunch on the new channel
|
SetChannelActorForDestroy(Channel, PriorityActors[j]->DestructionInfo); // Send a close bunch on the new channel
|
||||||
Connection_DestroyedStartupOrDormantActors.Remove(PriorityActors[j]->DestructionInfo->NetGUID); // Remove from connections to-be-destroyed list (close bunch of reliable, so it will make it there)
|
Connection_DestroyedStartupOrDormantActors.Remove(PriorityActors[j]->DestructionInfo->NetGUID); // Remove from connections to-be-destroyed list (close bunch of reliable, so it will make it there)
|
||||||
}
|
}
|
||||||
@@ -659,6 +760,7 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
|||||||
|
|
||||||
// Normal actor replication
|
// Normal actor replication
|
||||||
UActorChannel* Channel = PriorityActors[j]->Channel;
|
UActorChannel* Channel = PriorityActors[j]->Channel;
|
||||||
|
|
||||||
if (!Channel || Channel->GetActor()) //make sure didn't just close this channel
|
if (!Channel || Channel->GetActor()) //make sure didn't just close this channel
|
||||||
{
|
{
|
||||||
AActor* Actor = ActorInfo->Actor;
|
AActor* Actor = ActorInfo->Actor;
|
||||||
@@ -672,19 +774,36 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
|||||||
// bTearOff actors should never be checked
|
// bTearOff actors should never be checked
|
||||||
if (bLevelInitializedForActor)
|
if (bLevelInitializedForActor)
|
||||||
{
|
{
|
||||||
if (!Actor->IsTearOff() && (!Channel || GetTime() - Channel->GetRelevantTime() > 1.f))
|
// if (!Actor->IsTearOff() && (!Channel || GetTime() - Channel->GetRelevantTime() > 1.f))
|
||||||
|
if (!Actor->IsTearOff())
|
||||||
{
|
{
|
||||||
if (IsActorRelevantToConnection(Actor, ConnectionViewers))
|
// Test3(Actor, "Passed first check");
|
||||||
|
|
||||||
|
if ((!Channel || GetTime() - Channel->GetRelevantTime() > 1.f))
|
||||||
{
|
{
|
||||||
bIsRelevant = true;
|
// Test3(Actor, "Passed SECOND check");
|
||||||
|
|
||||||
|
if (IsActorRelevantToConnection(Actor, ConnectionViewers))
|
||||||
|
{
|
||||||
|
// Test3(Actor, "Passed THIRD check");
|
||||||
|
bIsRelevant = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Test3(Actor, "FAiled second check");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Test3(Actor, "Failed first check");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the actor is now relevant or was recently relevant
|
// if the actor is now relevant or was recently relevant
|
||||||
const bool bIsRecentlyRelevant = bIsRelevant || (Channel && GetTime() - Channel->GetRelevantTime() < GetRelevantTimeout()) || ActorInfo->bForceRelevantNextUpdate;
|
const bool bIsRecentlyRelevant = bIsRelevant || (Channel && GetTime() - Channel->GetRelevantTime() < GetRelevantTimeout()) || ActorInfo->bForceRelevantNextUpdate;
|
||||||
|
|
||||||
// Test2(Actor, std::format("bIsRecentlyRelevant: {} Channel: {} bIsRelevant: {}", (int)bIsRecentlyRelevant, __int64(Channel), (int)bIsRelevant));
|
// Test3(Actor, std::format("bIsRecentlyRelevant: {} bLevelInitializedForActor: {} Channel: {} bIsRelevant: {}", (int)bIsRecentlyRelevant, bLevelInitializedForActor, __int64(Channel), (int)bIsRelevant));
|
||||||
// Test2(Actor, std::format("bIsRelevant: {} bLevelInitializedForActor: {} Cond: {}", bIsRelevant, bLevelInitializedForActor, !Actor->IsTearOff() && (!Channel || GetTime() - Channel->GetRelevantTime() > 1.f)));
|
// Test2(Actor, std::format("bIsRelevant: {} bLevelInitializedForActor: {} Cond: {}", bIsRelevant, bLevelInitializedForActor, !Actor->IsTearOff() && (!Channel || GetTime() - Channel->GetRelevantTime() > 1.f)));
|
||||||
// Test2(Actor, std::format("TearOff: {} GetTime(): {} Channel->GetRelevantTime(): {}", !Actor->IsTearOff(), GetTime(), Channel ? Channel->GetRelevantTime() : 99));
|
// Test2(Actor, std::format("TearOff: {} GetTime(): {} Channel->GetRelevantTime(): {}", !Actor->IsTearOff(), GetTime(), Channel ? Channel->GetRelevantTime() : 99));
|
||||||
|
|
||||||
@@ -694,7 +813,10 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
|||||||
{
|
{
|
||||||
FinalRelevantCount++;
|
FinalRelevantCount++;
|
||||||
|
|
||||||
if (Channel == NULL) // && GuidCache->SupportsObject(Actor->GetClass()) && GuidCache->SupportsObject(Actor->IsNetStartupActor() ? Actor : Actor->GetArchetype()))
|
if (Channel == NULL
|
||||||
|
/* && GetGuidCache()->SupportsObject(Actor->ClassPrivate)
|
||||||
|
&& GetGuidCache()->SupportsObject(Actor->IsNetStartupActor() ? Actor : Actor->GetArchetype()) */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (bLevelInitializedForActor)
|
if (bLevelInitializedForActor)
|
||||||
{
|
{
|
||||||
@@ -709,7 +831,7 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
|||||||
// if we couldn't replicate it for a reason that should be temporary, and this Actor is updated very infrequently, make sure we update it again soon
|
// if we couldn't replicate it for a reason that should be temporary, and this Actor is updated very infrequently, make sure we update it again soon
|
||||||
else if (Actor->GetNetUpdateFrequency() < 1.0f)
|
else if (Actor->GetNetUpdateFrequency() < 1.0f)
|
||||||
{
|
{
|
||||||
auto TimeSeconds = UGameplayStatics::GetTimeSeconds(GetWorld()); // Actor->GetWorld()->TimeSeconds
|
auto TimeSeconds = GetTimeSecondsForWorld(GetWorld()); // Actor->GetWorld()->TimeSeconds
|
||||||
ActorInfo->NextUpdateTime = TimeSeconds + 0.2f * FRand();
|
ActorInfo->NextUpdateTime = TimeSeconds + 0.2f * FRand();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -719,26 +841,39 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
|||||||
// if it is relevant then mark the channel as relevant for a short amount of time
|
// if it is relevant then mark the channel as relevant for a short amount of time
|
||||||
if (bIsRelevant)
|
if (bIsRelevant)
|
||||||
{
|
{
|
||||||
|
// Channel->GetRelevantTime() = GetTime() - 1.0; // + 0.5f * SRand(); // scufed fn wtf
|
||||||
Channel->GetRelevantTime() = GetTime() + 0.5f * SRand();
|
Channel->GetRelevantTime() = GetTime() + 0.5f * SRand();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ReplicateActor(Channel))
|
if (Channel->IsNetReady(0))
|
||||||
{
|
{
|
||||||
ActorUpdatesThisConnectionSent++;
|
if (ReplicateActor(Channel))
|
||||||
|
{
|
||||||
|
ActorUpdatesThisConnectionSent++;
|
||||||
|
|
||||||
// Calculate min delta (max rate actor will upate), and max delta (slowest rate actor will update)
|
// Calculate min delta (max rate actor will upate), and max delta (slowest rate actor will update)
|
||||||
const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency();
|
const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency();
|
||||||
const float MaxOptimalDelta = FMath::Max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta);
|
const float MaxOptimalDelta = FMath::Max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta);
|
||||||
const float DeltaBetweenReplications = (UGameplayStatics::GetTimeSeconds(GetWorld()) - ActorInfo->LastNetReplicateTime);
|
const float DeltaBetweenReplications = (GetTimeSecondsForWorld(GetWorld()) - ActorInfo->LastNetReplicateTime);
|
||||||
|
|
||||||
// Choose an optimal time, we choose 70% of the actual rate to allow frequency to go up if needed
|
// Choose an optimal time, we choose 70% of the actual rate to allow frequency to go up if needed
|
||||||
ActorInfo->OptimalNetUpdateDelta = FMath::Clamp(DeltaBetweenReplications * 0.7f, MinOptimalDelta, MaxOptimalDelta);
|
ActorInfo->OptimalNetUpdateDelta = FMath::Clamp(DeltaBetweenReplications * 0.7f, MinOptimalDelta, MaxOptimalDelta);
|
||||||
ActorInfo->LastNetReplicateTime = UGameplayStatics::GetTimeSeconds(GetWorld());
|
ActorInfo->LastNetReplicateTime = GetTimeSecondsForWorld(GetWorld());
|
||||||
ReplicatedActors.emplace(Actor->GetFullName());
|
// ReplicatedActors.emplace(Actor->GetFullName());
|
||||||
|
}
|
||||||
|
|
||||||
|
ActorUpdatesThisConnection++;
|
||||||
|
OutUpdated++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Actor->ForceNetUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
ActorUpdatesThisConnection++;
|
if (!Connection->IsNetReady(0))
|
||||||
OutUpdated++;
|
{
|
||||||
|
return j;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,6 +887,8 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection*
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LOG_INFO(LogDev, "FinalRelevantCount: {} ActorUpdatesThisConnection: {} ActorUpdatesThisConnectionSent: {}", FinalRelevantCount, ActorUpdatesThisConnection, ActorUpdatesThisConnectionSent);
|
||||||
|
|
||||||
return FinalSortedCount;
|
return FinalSortedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,15 +906,17 @@ int32 UNetDriver::ServerReplicateActors()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AFortWorldSettings* WorldSettings = GetFortWorldSettings(NetDriver->World);
|
auto World = GetNetDriverWorld();
|
||||||
|
|
||||||
|
AWorldSettings* WorldSettings = World->GetWorldSettings();
|
||||||
|
|
||||||
// bool bCPUSaturated = false;
|
// bool bCPUSaturated = false;
|
||||||
float ServerTickTime = 30.f; // Globals::MaxTickRate; // GEngine->GetMaxTickRate(DeltaSeconds);
|
float ServerTickTime = GetMaxTickRateHook();
|
||||||
/* if (ServerTickTime == 0.f)
|
if (ServerTickTime == 0.f)
|
||||||
{
|
{
|
||||||
ServerTickTime = DeltaSeconds;
|
// ServerTickTime = DeltaSeconds;
|
||||||
}
|
}
|
||||||
else */
|
else
|
||||||
{
|
{
|
||||||
ServerTickTime = 1.f / ServerTickTime;
|
ServerTickTime = 1.f / ServerTickTime;
|
||||||
// bCPUSaturated = DeltaSeconds > 1.2f * ServerTickTime;
|
// bCPUSaturated = DeltaSeconds > 1.2f * ServerTickTime;
|
||||||
@@ -789,9 +928,7 @@ int32 UNetDriver::ServerReplicateActors()
|
|||||||
|
|
||||||
// std::cout << "ConsiderList.size(): " << GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num() << '\n';
|
// std::cout << "ConsiderList.size(): " << GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num() << '\n';
|
||||||
|
|
||||||
auto World = GetWorld();
|
ServerReplicateActors_BuildConsiderList(ConsiderList, ServerTickTime);
|
||||||
|
|
||||||
ServerReplicateActors_BuildConsiderList(ConsiderList);
|
|
||||||
|
|
||||||
bool bCPUSaturated = false;
|
bool bCPUSaturated = false;
|
||||||
|
|
||||||
@@ -804,7 +941,19 @@ int32 UNetDriver::ServerReplicateActors()
|
|||||||
if (!Connection)
|
if (!Connection)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// idk some dormancy validate stuff should go here
|
// net.DormancyValidate can be set to 2 to validate all dormant actors against last known state before going dormant
|
||||||
|
/* if (CVarNetDormancyValidate.GetValueOnAnyThread() == 2)
|
||||||
|
{
|
||||||
|
for (auto It = Connection->DormantReplicatorMap.CreateIterator(); It; ++It)
|
||||||
|
{
|
||||||
|
FObjectReplicator& Replicator = It.Value().Get();
|
||||||
|
|
||||||
|
if (Replicator.OwningChannel != nullptr)
|
||||||
|
{
|
||||||
|
Replicator.ValidateAgainstState(Replicator.OwningChannel->GetActor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
// if this client shouldn't be ticked this frame
|
// if this client shouldn't be ticked this frame
|
||||||
if (i >= NumClientsToTick)
|
if (i >= NumClientsToTick)
|
||||||
@@ -819,18 +968,7 @@ int32 UNetDriver::ServerReplicateActors()
|
|||||||
{
|
{
|
||||||
// find the channel
|
// find the channel
|
||||||
|
|
||||||
UActorChannel* Channel = nullptr;
|
UActorChannel* Channel = FindChannel(Connection, ConsiderList[ConsiderIdx]);
|
||||||
|
|
||||||
auto& ActorChannels = Connection->GetActorChannels();
|
|
||||||
|
|
||||||
for (int i = 0; i < ActorChannels.Pairs.Num(); i++)
|
|
||||||
{
|
|
||||||
if (ActorChannels.Pairs[i].First == ConsiderList[ConsiderIdx]->WeakActor)
|
|
||||||
{
|
|
||||||
Channel = ActorChannels.Pairs[i].Second;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// and if the channel last update time doesn't match the last net update time for the actor
|
// and if the channel last update time doesn't match the last net update time for the actor
|
||||||
if (Channel != NULL && Channel->GetLastUpdateTime() < ConsiderList[ConsiderIdx]->LastNetUpdateTime)
|
if (Channel != NULL && Channel->GetLastUpdateTime() < ConsiderList[ConsiderIdx]->LastNetUpdateTime)
|
||||||
@@ -840,7 +978,8 @@ int32 UNetDriver::ServerReplicateActors()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connection->TimeSensitive = false; // TODO Milxnor
|
static auto TimeSensitiveOffset = 0x241;
|
||||||
|
Connection->Get<bool>(TimeSensitiveOffset) = false;
|
||||||
}
|
}
|
||||||
else if (Connection->GetViewTarget())
|
else if (Connection->GetViewTarget())
|
||||||
{
|
{
|
||||||
@@ -849,7 +988,6 @@ int32 UNetDriver::ServerReplicateActors()
|
|||||||
|
|
||||||
// ConnectionViewers.Reset();
|
// ConnectionViewers.Reset();
|
||||||
std::vector<FNetViewer> ConnectionViewers;
|
std::vector<FNetViewer> ConnectionViewers;
|
||||||
// new(ConnectionViewers)FNetViewer(Connection, DeltaSeconds);
|
|
||||||
ConnectionViewers.push_back(ConstructNetViewer(Connection));
|
ConnectionViewers.push_back(ConstructNetViewer(Connection));
|
||||||
|
|
||||||
// send ClientAdjustment if necessary
|
// send ClientAdjustment if necessary
|
||||||
@@ -899,24 +1037,24 @@ int32 UNetDriver::ServerReplicateActors()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConnectionViewers.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// shuffle the list of connections if not all connections were ticked
|
// shuffle the list of connections if not all connections were ticked
|
||||||
/*
|
/* if (NumClientsToTick < ClientConnections.Num())
|
||||||
if (NumClientsToTick < NetDriver->ClientConnections.Num())
|
|
||||||
{
|
{
|
||||||
int32 NumConnectionsToMove = NumClientsToTick;
|
int32 NumConnectionsToMove = NumClientsToTick;
|
||||||
while (NumConnectionsToMove > 0)
|
while (NumConnectionsToMove > 0)
|
||||||
{
|
{
|
||||||
// move all the ticked connections to the end of the list so that the other connections are considered first for the next frame
|
// move all the ticked connections to the end of the list so that the other connections are considered first for the next frame
|
||||||
UNetConnection* Connection = NetDriver->ClientConnections[0];
|
UNetConnection* Connection = ClientConnections.at(0);
|
||||||
NetDriver->ClientConnections.RemoveAt(0, 1);
|
ClientConnections.RemoveAt(0, 1);
|
||||||
NetDriver->ClientConnections.Add(Connection);
|
ClientConnections.Add(Connection);
|
||||||
NumConnectionsToMove--;
|
NumConnectionsToMove--;
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
*/
|
|
||||||
|
|
||||||
return Updated;
|
return Updated;
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,7 @@ struct FActorDestructionInfo
|
|||||||
FString PathName;
|
FString PathName;
|
||||||
FName StreamingLevelName;
|
FName StreamingLevelName;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FNetworkObjectInfo
|
struct FNetworkObjectInfo
|
||||||
{
|
{
|
||||||
/** Pointer to the replicated actor. */
|
/** Pointer to the replicated actor. */
|
||||||
@@ -109,6 +110,16 @@ struct FURL // idk where this actually goes
|
|||||||
FString Portal; // 0x0058(0x0010) (ZeroConstructor)
|
FString Portal; // 0x0058(0x0010) (ZeroConstructor)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FNetGUIDCache
|
||||||
|
{
|
||||||
|
bool SupportsObject(const UObject* Object, const TWeakObjectPtr<UObject>* WeakObjectPtr = nullptr) const
|
||||||
|
{
|
||||||
|
// 1.11
|
||||||
|
bool (*SupportsObjectOriginal)(__int64, const UObject*, const TWeakObjectPtr<UObject>*) = decltype(SupportsObjectOriginal)(__int64(GetModuleHandleW(0)) + 0x1AF01E0);
|
||||||
|
return SupportsObjectOriginal(__int64(this), Object, WeakObjectPtr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class UNetDriver : public UObject
|
class UNetDriver : public UObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -119,6 +130,18 @@ public:
|
|||||||
|
|
||||||
static void TickFlushHook(UNetDriver* NetDriver);
|
static void TickFlushHook(UNetDriver* NetDriver);
|
||||||
|
|
||||||
|
FNetGUIDCache* GetGuidCache()
|
||||||
|
{
|
||||||
|
static auto GuidCacheOffset = GetOffset("WorldPackage") + 8; // checked for 1.11
|
||||||
|
return GetPtr<FNetGUIDCache>(GuidCacheOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
UWorld*& GetNetDriverWorld() const
|
||||||
|
{
|
||||||
|
static auto WorldOffset = GetOffset("World");
|
||||||
|
return Get<UWorld*>(WorldOffset);
|
||||||
|
}
|
||||||
|
|
||||||
UObject*& GetWorldPackage() const
|
UObject*& GetWorldPackage() const
|
||||||
{
|
{
|
||||||
static auto WorldPackageOffset = GetOffset("WorldPackage");
|
static auto WorldPackageOffset = GetOffset("WorldPackage");
|
||||||
@@ -161,7 +184,7 @@ public:
|
|||||||
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_ProcessPrioritizedActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, FActorPriority** PriorityActors, const int32 FinalSortedCount, int32& OutUpdated);
|
||||||
void ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList);
|
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, FActorPriority*& OutPriorityList, FActorPriority**& OutPriorityActors);
|
||||||
FNetworkObjectList& GetNetworkObjectList();
|
FNetworkObjectList& GetNetworkObjectList();
|
||||||
};
|
};
|
||||||
@@ -31,7 +31,7 @@ public:
|
|||||||
FName NamePrivate;
|
FName NamePrivate;
|
||||||
UObject* OuterPrivate;
|
UObject* OuterPrivate;
|
||||||
|
|
||||||
static inline void (*ProcessEventOriginal)(UObject*, UFunction*, void*);
|
static inline void (*ProcessEventOriginal)(const UObject*, UFunction*, void*);
|
||||||
|
|
||||||
/* virtual */ void ProcessEvent(UFunction* Function, void* Parms = nullptr)
|
/* virtual */ void ProcessEvent(UFunction* Function, void* Parms = nullptr)
|
||||||
{
|
{
|
||||||
@@ -39,6 +39,12 @@ public:
|
|||||||
ProcessEventOriginal(this, Function, Parms);
|
ProcessEventOriginal(this, Function, Parms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* virtual */ void ProcessEvent(UFunction* Function, void* Parms = nullptr) const
|
||||||
|
{
|
||||||
|
// LOG_INFO(LogDev, "PE: 0x{:x}", __int64(ProcessEventOriginal) - __int64(GetModuleHandleW(0)));
|
||||||
|
ProcessEventOriginal(this, Function, Parms);
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetName() { return NamePrivate.ToString(); }
|
std::string GetName() { return NamePrivate.ToString(); }
|
||||||
std::string GetFullName();
|
std::string GetFullName();
|
||||||
|
|
||||||
|
|||||||
@@ -175,6 +175,7 @@
|
|||||||
<ClCompile Include="BuildingWeapons.cpp" />
|
<ClCompile Include="BuildingWeapons.cpp" />
|
||||||
<ClCompile Include="Class.cpp" />
|
<ClCompile Include="Class.cpp" />
|
||||||
<ClCompile Include="Controller.cpp" />
|
<ClCompile Include="Controller.cpp" />
|
||||||
|
<ClCompile Include="DataChannel.cpp" />
|
||||||
<ClCompile Include="DataTableFunctionLibrary.cpp" />
|
<ClCompile Include="DataTableFunctionLibrary.cpp" />
|
||||||
<ClCompile Include="dllmain.cpp" />
|
<ClCompile Include="dllmain.cpp" />
|
||||||
<ClCompile Include="EngineTypes.cpp" />
|
<ClCompile Include="EngineTypes.cpp" />
|
||||||
|
|||||||
@@ -179,6 +179,9 @@
|
|||||||
<ClCompile Include="EngineTypes.cpp">
|
<ClCompile Include="EngineTypes.cpp">
|
||||||
<Filter>Engine\Source\Runtime\Engine\Private</Filter>
|
<Filter>Engine\Source\Runtime\Engine\Private</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="DataChannel.cpp">
|
||||||
|
<Filter>Engine\Source\Runtime\Engine\Private</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="log.h" />
|
<ClInclude Include="log.h" />
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ public:
|
|||||||
return It.GetIndex();
|
return It.GetIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
FORCEINLINE bool Remove(const SetType& ElementToRemove)
|
FORCEINLINE bool Remove(const SetType& ElementToRemove)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Array.h"
|
#include "Array.h"
|
||||||
#include "BitArray.h"
|
#include "BitArray.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
template <typename ElementType>
|
template <typename ElementType>
|
||||||
union TSparseArrayElementOrListLink
|
union TSparseArrayElementOrListLink
|
||||||
@@ -161,11 +162,17 @@ public:
|
|||||||
|
|
||||||
FORCEINLINE bool RemoveAt(const int32 IndexToRemove)
|
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))
|
if (IndexToRemove >= 0 && IndexToRemove < Data.Num() && AllocationFlags.IsSet(IndexToRemove))
|
||||||
{
|
{
|
||||||
int32 PreviousFreeIndex = -1;
|
int32 PreviousFreeIndex = -1;
|
||||||
int32 NextFreeIndex = -1;
|
int32 NextFreeIndex = -1;
|
||||||
|
|
||||||
|
LOG_INFO(LogDev, "NumFreeIndices: {}", NumFreeIndices);
|
||||||
|
|
||||||
/* if (NumFreeIndices == 0)
|
/* if (NumFreeIndices == 0)
|
||||||
{
|
{
|
||||||
FirstFreeIndex = IndexToRemove;
|
FirstFreeIndex = IndexToRemove;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
class FString
|
class FString
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
TArray<TCHAR> Data;
|
TArray<TCHAR> Data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ public:
|
|||||||
|
|
||||||
bool operator==(const FWeakObjectPtr& other)
|
bool operator==(const FWeakObjectPtr& other)
|
||||||
{
|
{
|
||||||
return ObjectIndex == other.ObjectIndex && ObjectSerialNumber == other.ObjectSerialNumber; // i need to check in ue if we check serialnumber
|
return ObjectIndex == other.ObjectIndex && ObjectSerialNumber == other.ObjectSerialNumber;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
#include "reboot.h"
|
#include "reboot.h"
|
||||||
|
|
||||||
UObject* UWorld::K2_GetWorldSettings()
|
AWorldSettings* UWorld::K2_GetWorldSettings()
|
||||||
{
|
{
|
||||||
static auto fn = FindObject<UFunction>("/Script/Engine.World.K2_GetWorldSettings");
|
static auto fn = FindObject<UFunction>("/Script/Engine.World.K2_GetWorldSettings");
|
||||||
UObject* WorldSettings;
|
AWorldSettings* WorldSettings;
|
||||||
this->ProcessEvent(fn, &WorldSettings);
|
this->ProcessEvent(fn, &WorldSettings);
|
||||||
return WorldSettings;
|
return WorldSettings;
|
||||||
}
|
}
|
||||||
@@ -80,4 +80,36 @@ void UWorld::Listen()
|
|||||||
*(UNetDriver**)(__int64(LevelCollections.AtPtr(1, LevelCollectionSize)) + 0x10) = NewNetDriver;
|
*(UNetDriver**)(__int64(LevelCollections.AtPtr(1, LevelCollectionSize)) + 0x10) = NewNetDriver;
|
||||||
|
|
||||||
LOG_INFO(LogNet, "Listening on port {}!", Port + AmountOfRestarts);
|
LOG_INFO(LogNet, "Listening on port {}!", Port + AmountOfRestarts);
|
||||||
|
}
|
||||||
|
|
||||||
|
AWorldSettings* UWorld::GetWorldSettings(const bool bCheckStreamingPersistent, const bool bChecked) const
|
||||||
|
{
|
||||||
|
// checkSlow(!IsInActualRenderingThread());
|
||||||
|
AWorldSettings* WorldSettings = nullptr;
|
||||||
|
static auto PersistentLevelOffset = GetOffset("PersistentLevel");
|
||||||
|
if (Get(PersistentLevelOffset))
|
||||||
|
{
|
||||||
|
WorldSettings = Get<ULevel*>(PersistentLevelOffset)->GetWorldSettings(bChecked);
|
||||||
|
|
||||||
|
if (bCheckStreamingPersistent)
|
||||||
|
{
|
||||||
|
static auto StreamingLevelsOffset = GetOffset("StreamingLevels");
|
||||||
|
auto& StreamingLevels = Get<TArray<UObject*>>(StreamingLevelsOffset);
|
||||||
|
|
||||||
|
static auto LevelStreamingPersistentClass = FindObject<UClass>("/Script/Engine.LevelStreamingPersistent");
|
||||||
|
|
||||||
|
if (StreamingLevels.Num() > 0 &&
|
||||||
|
StreamingLevels.at(0) &&
|
||||||
|
StreamingLevels.at(0)->IsA(LevelStreamingPersistentClass))
|
||||||
|
{
|
||||||
|
static auto LoadedLevelOffset = StreamingLevels.at(0)->GetOffset("LoadedLevel");
|
||||||
|
ULevel* Level = StreamingLevels.at(0)->Get<ULevel*>(LoadedLevelOffset);
|
||||||
|
if (Level != nullptr)
|
||||||
|
{
|
||||||
|
WorldSettings = Level->GetWorldSettings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return WorldSettings;
|
||||||
}
|
}
|
||||||
@@ -4,12 +4,18 @@
|
|||||||
#include "Transform.h"
|
#include "Transform.h"
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "Rotator.h"
|
#include "Rotator.h"
|
||||||
|
#include "Actor.h"
|
||||||
|
|
||||||
struct FNetworkNotify
|
struct FNetworkNotify
|
||||||
{
|
{
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AWorldSettings : public AActor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
struct FActorSpawnParameters
|
struct FActorSpawnParameters
|
||||||
{
|
{
|
||||||
FName Name;
|
FName Name;
|
||||||
@@ -56,7 +62,8 @@ public:
|
|||||||
return SpawnActor<ActorType>(Class, UserTransformPtr, SpawnParameters);
|
return SpawnActor<ActorType>(Class, UserTransformPtr, SpawnParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
UObject* K2_GetWorldSettings();
|
AWorldSettings* GetWorldSettings(bool bCheckStreamingPersistent = false, bool bChecked = true) const;
|
||||||
|
AWorldSettings* K2_GetWorldSettings();
|
||||||
|
|
||||||
void Listen();
|
void Listen();
|
||||||
};
|
};
|
||||||
@@ -44,7 +44,6 @@ static ENetMode GetNetModeHook() { return NetMode; }
|
|||||||
static ENetMode GetNetModeHook2() { return NetMode; }
|
static ENetMode GetNetModeHook2() { return NetMode; }
|
||||||
|
|
||||||
static bool ReturnTrueHook() { return true; }
|
static bool ReturnTrueHook() { return true; }
|
||||||
static float GetMaxTickRateHook() { return 30.f; }
|
|
||||||
static int Return2Hook() { return 2; }
|
static int Return2Hook() { return 2; }
|
||||||
|
|
||||||
static void NoMCPHook() { return; }
|
static void NoMCPHook() { return; }
|
||||||
@@ -133,6 +132,9 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
static auto AthenaMarkerComponentDefault = FindObject<UAthenaMarkerComponent>(L"/Script/FortniteGame.Default__AthenaMarkerComponent");
|
static auto AthenaMarkerComponentDefault = FindObject<UAthenaMarkerComponent>(L"/Script/FortniteGame.Default__AthenaMarkerComponent");
|
||||||
static auto FortWeaponDefault = FindObject<AFortWeapon>(L"/Script/FortniteGame.Default__FortWeapon");
|
static auto FortWeaponDefault = FindObject<AFortWeapon>(L"/Script/FortniteGame.Default__FortWeapon");
|
||||||
|
|
||||||
|
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogNetPackageMap VeryVerbose", nullptr);
|
||||||
|
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogNetTraffic VeryVerbose", nullptr);
|
||||||
|
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogNet VeryVerbose", nullptr);
|
||||||
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogBuilding VeryVerbose", nullptr);
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogBuilding VeryVerbose", nullptr);
|
||||||
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFortUIDirector NoLogging", nullptr);
|
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFortUIDirector NoLogging", nullptr);
|
||||||
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogAbilitySystem VeryVerbose", nullptr);
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogAbilitySystem VeryVerbose", nullptr);
|
||||||
@@ -242,7 +244,14 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto func : Addresses::GetFunctionsToNull())
|
auto AddressesToNull = Addresses::GetFunctionsToNull();
|
||||||
|
|
||||||
|
auto ServerCheatAllIndex = GetFunctionIdxOrPtr(FindObject<UFunction>("/Script/FortniteGame.FortPlayerController.ServerCheatAll"));
|
||||||
|
|
||||||
|
if (ServerCheatAllIndex)
|
||||||
|
AddressesToNull.push_back(FortPlayerControllerAthenaDefault->VFTable[ServerCheatAllIndex / 8]);
|
||||||
|
|
||||||
|
for (auto func : AddressesToNull)
|
||||||
{
|
{
|
||||||
if (func == 0)
|
if (func == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -974,7 +974,7 @@ static inline uint64 FindGIsClient()
|
|||||||
// return __int64(GetModuleHandleW(0)) + 0x46AD734;
|
// return __int64(GetModuleHandleW(0)) + 0x46AD734;
|
||||||
if (Fortnite_Version == 1.72)
|
if (Fortnite_Version == 1.72)
|
||||||
return __int64(GetModuleHandleW(0)) + 0x6536B65;
|
return __int64(GetModuleHandleW(0)) + 0x6536B65;
|
||||||
if (Fortnite_Version == 1.8)
|
if (Fortnite_Version == 1.8)
|
||||||
return __int64(GetModuleHandleW(0)) + 0x66637E5;
|
return __int64(GetModuleHandleW(0)) + 0x66637E5;
|
||||||
if (Fortnite_Version == 1.11)
|
if (Fortnite_Version == 1.11)
|
||||||
return __int64(GetModuleHandleW(0)) + 0x5BAA38F;
|
return __int64(GetModuleHandleW(0)) + 0x5BAA38F;
|
||||||
@@ -1125,8 +1125,11 @@ static inline uint64 FindPickTeam()
|
|||||||
{
|
{
|
||||||
if (Engine_Version == 426)
|
if (Engine_Version == 426)
|
||||||
{
|
{
|
||||||
auto testAddr = Memcury::Scanner::FindPattern("88 54 24 10 53 56 41 54 41 55 41 56 48 83 EC 60 4C 8B A1").Get(); // 14.60 what is happening lol ????
|
auto testAddr = Memcury::Scanner::FindPattern("88 54 24 10 53 56 41 54 41 55 41 56 48 83 EC 60 4C 8B A1", false).Get(); // 14.60 what is happening lol ????
|
||||||
|
|
||||||
|
if (!testAddr)
|
||||||
|
testAddr = Memcury::Scanner::FindPattern("88 54 24 10 53 55 56 41 55 41 56 48 83 EC 70 48 8B", false).Get(); // 15.10
|
||||||
|
|
||||||
if (testAddr)
|
if (testAddr)
|
||||||
return testAddr;
|
return testAddr;
|
||||||
}
|
}
|
||||||
@@ -1137,6 +1140,9 @@ static inline uint64 FindPickTeam()
|
|||||||
else if (Engine_Version >= 427) // different start
|
else if (Engine_Version >= 427) // different start
|
||||||
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 88 54 24 10 55 56 57 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 70 4C 8B A1").Get();
|
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 88 54 24 10 55 56 57 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 70 4C 8B A1").Get();
|
||||||
|
|
||||||
|
if (Fortnite_Version == 7.20)
|
||||||
|
return Memcury::Scanner::FindPattern("89 54 24 10 53 56 41 54 41 55 41 56 48 81 EC").Get();
|
||||||
|
|
||||||
auto Addr = Memcury::Scanner::FindStringRef(L"PickTeam for [%s] used beacon value [%d]", false, 0, Engine_Version >= 427); // todo check if its just s18+ but this doesn't matter for now cuz we hardcode sig
|
auto Addr = Memcury::Scanner::FindStringRef(L"PickTeam for [%s] used beacon value [%d]", false, 0, Engine_Version >= 427); // todo check if its just s18+ but this doesn't matter for now cuz we hardcode sig
|
||||||
|
|
||||||
if (!Addr.Get())
|
if (!Addr.Get())
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ inline __int64 GetIndexFromVirtualFunctionCall(__int64 NativeAddr)
|
|||||||
|
|
||||||
inline __int64 GetFunctionIdxOrPtr(UFunction* Function)
|
inline __int64 GetFunctionIdxOrPtr(UFunction* Function)
|
||||||
{
|
{
|
||||||
|
if (!Function)
|
||||||
|
return 0;
|
||||||
|
|
||||||
auto NativeAddr = __int64(Function->GetFunc());
|
auto NativeAddr = __int64(Function->GetFunc());
|
||||||
|
|
||||||
auto FuncName = Function->GetName();
|
auto FuncName = Function->GetName();
|
||||||
|
|||||||
@@ -306,4 +306,8 @@ namespace MemberOffsets
|
|||||||
{
|
{
|
||||||
extern inline int bDBNO = 0, Downer = 0, FinisherOrDowner = 0, DeathCause = 0, Distance = 0, DeathLocation = 0, bInitialized = 0, DeathTags = 0;
|
extern inline int bDBNO = 0, Downer = 0, FinisherOrDowner = 0, DeathCause = 0, Distance = 0, DeathLocation = 0, bInitialized = 0, DeathTags = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float GetMaxTickRateHook() { return 30.f; }
|
||||||
|
|
||||||
|
#define VALIDATEOFFSET(offset) if (!offset) LOG_WARN(LogDev, "[{}] Invalid offset", __FUNCTIONNAME__);
|
||||||
Reference in New Issue
Block a user