mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
performace
This commit is contained in:
@@ -17,6 +17,11 @@ FNetworkObjectList& UNetDriver::GetNetworkObjectList()
|
||||
return *(*(TSharedPtr<FNetworkObjectList>*)(__int64(this) + Offsets::NetworkObjectList));
|
||||
}
|
||||
|
||||
bool ShouldUseNetworkObjectList()
|
||||
{
|
||||
return Fortnite_Version < 20;
|
||||
}
|
||||
|
||||
void UNetDriver::RemoveNetworkActor(AActor* Actor)
|
||||
{
|
||||
GetNetworkObjectList().Remove(Actor);
|
||||
@@ -35,7 +40,8 @@ void UNetDriver::TickFlushHook(UNetDriver* NetDriver)
|
||||
{
|
||||
static auto ReplicationDriverOffset = NetDriver->GetOffset("ReplicationDriver", false);
|
||||
|
||||
if (ReplicationDriverOffset == -1)
|
||||
// if (ReplicationDriverOffset == -1)
|
||||
if (ReplicationDriverOffset == -1 || Fortnite_Version >= 20)
|
||||
{
|
||||
NetDriver->ServerReplicateActors();
|
||||
}
|
||||
@@ -149,98 +155,148 @@ void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObj
|
||||
{
|
||||
std::vector<AActor*> ActorsToRemove;
|
||||
|
||||
auto& ActiveObjects = GetNetworkObjectList().ActiveNetworkObjects;
|
||||
|
||||
auto World = GetWorld();
|
||||
|
||||
for (const TSharedPtr<FNetworkObjectInfo>& ActorInfo : ActiveObjects)
|
||||
if (ShouldUseNetworkObjectList())
|
||||
{
|
||||
if (!ActorInfo->bPendingNetUpdate && UGameplayStatics::GetTimeSeconds(GetWorld()) <= ActorInfo->NextUpdateTime)
|
||||
auto& ActiveObjects = GetNetworkObjectList().ActiveNetworkObjects;
|
||||
|
||||
auto World = GetWorld();
|
||||
|
||||
for (const TSharedPtr<FNetworkObjectInfo>& ActorInfo : ActiveObjects)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto Actor = ActorInfo->Actor;
|
||||
|
||||
if (!Actor)
|
||||
continue;
|
||||
|
||||
if (Actor->IsPendingKillPending())
|
||||
// if (Actor->IsPendingKill())
|
||||
{
|
||||
ActorsToRemove.push_back(Actor);
|
||||
continue;
|
||||
}
|
||||
|
||||
static auto RemoteRoleOffset = Actor->GetOffset("RemoteRole");
|
||||
|
||||
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->IsNetStartupActor()) // IsDormInitialStartupActor
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
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 = UGameplayStatics::GetTimeSeconds(World) - ActorInfo->LastNetReplicateTime;
|
||||
|
||||
if (LastReplicateDelta > ScaleDownStartTime)
|
||||
{
|
||||
static auto MinNetUpdateFrequencyOffset = Actor->GetOffset("MinNetUpdateFrequency");
|
||||
|
||||
if (Actor->Get<float>(MinNetUpdateFrequencyOffset) == 0.0f)
|
||||
if (!ActorInfo->bPendingNetUpdate && UGameplayStatics::GetTimeSeconds(GetWorld()) <= ActorInfo->NextUpdateTime)
|
||||
{
|
||||
Actor->Get<float>(MinNetUpdateFrequencyOffset) = 2.0f;
|
||||
continue;
|
||||
}
|
||||
|
||||
const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency(); // Don't go faster than NetUpdateFrequency
|
||||
const float MaxOptimalDelta = max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta); // Don't go slower than MinNetUpdateFrequency (or NetUpdateFrequency if it's slower)
|
||||
auto Actor = ActorInfo->Actor;
|
||||
|
||||
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 (!Actor)
|
||||
continue;
|
||||
|
||||
if (Actor->IsPendingKillPending())
|
||||
// if (Actor->IsPendingKill())
|
||||
{
|
||||
ActorsToRemove.push_back(Actor);
|
||||
continue;
|
||||
}
|
||||
|
||||
static auto RemoteRoleOffset = Actor->GetOffset("RemoteRole");
|
||||
|
||||
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->IsNetStartupActor()) // IsDormInitialStartupActor
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
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 = UGameplayStatics::GetTimeSeconds(World) - 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->GetMinNetUpdateFrequency(), 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 = UGameplayStatics::GetTimeSeconds(World) + FRand() * ServerTickTime + NextUpdateDelta;
|
||||
static auto TimeOffset = GetOffset("Time");
|
||||
ActorInfo->LastNetUpdateTime = Get<float>(TimeOffset);
|
||||
}
|
||||
|
||||
ActorInfo->bPendingNetUpdate = false;
|
||||
|
||||
OutConsiderList.push_back(ActorInfo.Get());
|
||||
|
||||
static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication);
|
||||
CallPreReplication(Actor, this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto Actors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass());
|
||||
|
||||
if (!ActorInfo->bPendingNetUpdate)
|
||||
for (int i = 0; i < Actors.Num(); ++i)
|
||||
{
|
||||
constexpr bool bUseAdapativeNetFrequency = false;
|
||||
const float NextUpdateDelta = bUseAdapativeNetFrequency ? ActorInfo->OptimalNetUpdateDelta : 1.0f / Actor->GetNetUpdateFrequency();
|
||||
auto Actor = Actors.at(i);
|
||||
|
||||
// then set the next update time
|
||||
float ServerTickTime = 1.f / 30;
|
||||
ActorInfo->NextUpdateTime = UGameplayStatics::GetTimeSeconds(World) + FRand() * ServerTickTime + NextUpdateDelta;
|
||||
static auto TimeOffset = GetOffset("Time");
|
||||
ActorInfo->LastNetUpdateTime = Get<float>(TimeOffset);
|
||||
if (Actor->IsPendingKillPending())
|
||||
// if (Actor->IsPendingKill())
|
||||
{
|
||||
ActorsToRemove.push_back(Actor);
|
||||
continue;
|
||||
}
|
||||
|
||||
static auto RemoteRoleOffset = Actor->GetOffset("RemoteRole");
|
||||
|
||||
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->IsNetStartupActor()) // IsDormInitialStartupActor
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto ActorInfo = new FNetworkObjectInfo;
|
||||
ActorInfo->Actor = Actor;
|
||||
|
||||
OutConsiderList.push_back(ActorInfo);
|
||||
|
||||
static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication);
|
||||
CallPreReplication(Actor, this);
|
||||
}
|
||||
|
||||
ActorInfo->bPendingNetUpdate = false;
|
||||
|
||||
OutConsiderList.push_back(ActorInfo.Get());
|
||||
|
||||
static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication);
|
||||
CallPreReplication(Actor, this);
|
||||
Actors.Free();
|
||||
}
|
||||
|
||||
for (auto Actor : ActorsToRemove)
|
||||
@@ -401,7 +457,9 @@ int32 UNetDriver::ServerReplicateActors()
|
||||
}
|
||||
|
||||
std::vector<FNetworkObjectInfo*> ConsiderList;
|
||||
ConsiderList.reserve(GetNetworkObjectList().ActiveNetworkObjects.Num());
|
||||
|
||||
if (ShouldUseNetworkObjectList())
|
||||
ConsiderList.reserve(GetNetworkObjectList().ActiveNetworkObjects.Num());
|
||||
|
||||
// std::cout << "ConsiderList.size(): " << GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num() << '\n';
|
||||
|
||||
@@ -424,10 +482,13 @@ int32 UNetDriver::ServerReplicateActors()
|
||||
if (!Connection->GetViewTarget())
|
||||
continue;
|
||||
|
||||
if (Connection->GetPlayerController())
|
||||
if (Addresses::SendClientAdjustment)
|
||||
{
|
||||
static void (*SendClientAdjustment)(APlayerController*) = decltype(SendClientAdjustment)(Addresses::SendClientAdjustment);
|
||||
SendClientAdjustment(Connection->GetPlayerController());
|
||||
if (Connection->GetPlayerController())
|
||||
{
|
||||
static void (*SendClientAdjustment)(APlayerController*) = decltype(SendClientAdjustment)(Addresses::SendClientAdjustment);
|
||||
SendClientAdjustment(Connection->GetPlayerController());
|
||||
}
|
||||
}
|
||||
|
||||
// Make weak ptr once for IsActorDormant call
|
||||
@@ -513,8 +574,15 @@ int32 UNetDriver::ServerReplicateActors()
|
||||
}
|
||||
}
|
||||
|
||||
enum class EChannelCreateFlags : uint32_t
|
||||
{
|
||||
None = (1 << 0),
|
||||
OpenedLocally = (1 << 1)
|
||||
};
|
||||
|
||||
static UChannel* (*CreateChannel)(UNetConnection*, int, bool, int32_t) = decltype(CreateChannel)(Addresses::CreateChannel);
|
||||
static __int64 (*ReplicateActor)(UActorChannel*) = decltype(ReplicateActor)(Addresses::ReplicateActor);
|
||||
static UObject* (*CreateChannelByName)(UNetConnection* Connection, FName* ChName, EChannelCreateFlags CreateFlags, int32_t ChannelIndex) = decltype(CreateChannelByName)(Addresses::CreateChannel);
|
||||
static __int64 (*SetChannelActor)(UActorChannel*, AActor*) = decltype(SetChannelActor)(Addresses::SetChannelActor);
|
||||
|
||||
if (!Channel)
|
||||
@@ -524,7 +592,18 @@ int32 UNetDriver::ServerReplicateActors()
|
||||
|
||||
if (bLevelInitializedForActor)
|
||||
{
|
||||
Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1);
|
||||
if (Engine_Version >= 422)
|
||||
{
|
||||
FString ActorStr = L"Actor";
|
||||
FName ActorName = UKismetStringLibrary::Conv_StringToName(ActorStr);
|
||||
|
||||
int ChannelIndex = -1; // 4294967295
|
||||
Channel = (UActorChannel*)CreateChannelByName(Connection, &ActorName, EChannelCreateFlags::OpenedLocally, ChannelIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1);
|
||||
}
|
||||
|
||||
if (Channel)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user