#include "NetDriver.h"

#include "reboot.h"
#include "Actor.h"
#include "NetConnection.h"
#include "FortPlayerControllerAthena.h"
#include "GameplayStatics.h"
#include "KismetMathLibrary.h"
#include <random>
#include "Package.h"
#include "AssertionMacros.h"
#include "ChildConnection.h"
#include "bots.h"
#include "NetworkingDistanceConstants.h"
#include "gui.h"

void UNetDriver::TickFlushHook(UNetDriver* NetDriver)
{
	if (bShouldDestroyAllPlayerBuilds) // i hate this
	{
		auto AllBuildingSMActors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), ABuildingSMActor::StaticClass());

		for (int i = 0; i < AllBuildingSMActors.Num(); i++)
		{
			auto CurrentBuildingSMActor = (ABuildingSMActor*)AllBuildingSMActors.at(i);

			if (CurrentBuildingSMActor->IsDestroyed() || CurrentBuildingSMActor->IsActorBeingDestroyed() || !CurrentBuildingSMActor->IsPlayerPlaced()) continue;

			CurrentBuildingSMActor->SilentDie();
			// CurrentBuildingSMActor->K2_DestroyActor();
		}

		AllBuildingSMActors.Free();
		bShouldDestroyAllPlayerBuilds = false;
	}
	
	/* if (bEnableBotTick)
	{
		Bots::Tick();
	} */

	if (Globals::bStartedListening)
	{
		if (!Globals::bShouldUseReplicationGraph)
		{
			NetDriver->ServerReplicateActors();
		}
		else
		{
			static auto ReplicationDriverOffset = NetDriver->GetOffset("ReplicationDriver"/*, false */);

			if (auto ReplicationDriver = NetDriver->Get(ReplicationDriverOffset))
			{
				reinterpret_cast<void(*)(UObject*)>(ReplicationDriver->VFTable[Offsets::ServerReplicateActors])(ReplicationDriver);
			}
			else
			{
				// LOG_INFO(LogDev, "ReplicationDriver is nul!!?1//33/221/4/124/123"); // 3.3 MOMENT
			}
		}
	}

	return TickFlushOriginal(NetDriver);
}

/*

Replication from Unreal Engine 4.19 (using std::vector instead of TArrays).

Can we make it faster? Perhaps removing references from some gets, but it shouldn't do crazy.

*/

FNetworkObjectList& UNetDriver::GetNetworkObjectList()
{
	return *(*(TSharedPtr<FNetworkObjectList>*)(__int64(this) + Offsets::NetworkObjectList));
}

void UNetDriver::RemoveNetworkActor(AActor* Actor) // T(REP)
{
	GetNetworkObjectList().Remove(Actor);

	// RenamedStartupActors.Remove(Actor->GetFName());
}


FActorPriority::FActorPriority(UNetConnection* InConnection, UActorChannel* InChannel, FNetworkObjectInfo* InActorInfo, const std::vector<FNetViewer>& Viewers, bool bLowBandwidth)
	: ActorInfo(InActorInfo), Channel(InChannel), DestructionInfo(NULL)
{
	float Time = Channel ? (InConnection->GetDriver()->GetTime() - Channel->GetLastUpdateTime()) : InConnection->GetDriver()->GetSpawnPrioritySeconds();
	// take the highest priority of the viewers on this connection
	Priority = 0;
	for (int32 i = 0; i < Viewers.size(); i++)
	{
		// Priority = FMath::Max<int32>(Priority, FMath::RoundToInt(65536.0f * 
		//		ActorInfo->Actor->GetNetPriority(Viewers[i].ViewLocation, Viewers[i].ViewDir, Viewers[i].InViewer, V[i].ViewTarget, InChannel, Time, bLowBandwidth)));
	}
}

FActorPriority::FActorPriority(class UNetConnection* InConnection, struct FActorDestructionInfo* Info, const std::vector<FNetViewer>& Viewers)
	: ActorInfo(NULL), Channel(NULL), DestructionInfo(Info)
{
	Priority = 0;

	for (int32 i = 0; i < Viewers.size(); i++)
	{
		float Time = InConnection->GetDriver()->GetSpawnPrioritySeconds();

		FVector Dir = DestructionInfo->DestroyedPosition - Viewers[i].ViewLocation;
		float DistSq = Dir.SizeSquared();

		// adjust priority based on distance and whether actor is in front of viewer
		if ((Viewers[i].ViewDir | Dir) < 0.f)
		{
			if (DistSq > NEARSIGHTTHRESHOLDSQUARED)
				Time *= 0.2f;
			else if (DistSq > CLOSEPROXIMITYSQUARED)
				Time *= 0.4f;
		}
		else if (DistSq > MEDSIGHTTHRESHOLDSQUARED)
			Time *= 0.4f;

		Priority = FMath::Max<int32>(Priority, 65536.0f * Time);
	}
}

bool UNetDriver::IsLevelInitializedForActor(const AActor* InActor, const UNetConnection* InConnection) const
{
	if (Fortnite_Version >= 2.42) // idk
	{
		return true;
	}

	/* #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) // (Milxnor) This is on some ue versions and others not.
		if (!InActor || !InConnection)
			return false;

		// check(World == InActor->GetWorld());
	#endif */

	bool bFirstWorldCheck = Engine_Version == 416
		? (InConnection->GetClientWorldPackageName() == GetWorld()->GetOutermost()->GetFName())
		: (InConnection->GetClientWorldPackageName() == GetWorldPackage()->NamePrivate);

	const bool bCorrectWorld = (bFirstWorldCheck && InConnection->ClientHasInitializedLevelFor(InActor));
	const bool bIsConnectionPC = (InActor == InConnection->GetPlayerController());
	return bCorrectWorld || bIsConnectionPC;
}

FNetViewer::FNetViewer(UNetConnection* InConnection, float DeltaSeconds) :
	Connection(InConnection),
	InViewer(InConnection->GetPlayerController() ? InConnection->GetPlayerController() : InConnection->GetOwningActor()),
	ViewTarget(InConnection->GetViewTarget()),
	ViewLocation(ForceInit),
	ViewDir(ForceInit)
{
	// check(InConnection->OwningActor);
	// check(!InConnection->PlayerController || (InConnection->PlayerController == InConnection->OwningActor));

	APlayerController* ViewingController = InConnection->GetPlayerController();

	// Get viewer coordinates.
	ViewLocation = ViewTarget->GetActorLocation();
	if (ViewingController)
	{
		FRotator ViewRotation = ViewingController->GetControlRotation();
		// ViewingController->GetPlayerViewPoint(ViewLocation, ViewRotation);
		ViewDir = ViewRotation.Vector();
	}
}

static FORCEINLINE bool IsActorRelevantToConnection(const AActor* Actor, const std::vector<FNetViewer>& ConnectionViewers)
{
	for (int32 viewerIdx = 0; viewerIdx < ConnectionViewers.size(); viewerIdx++)
	{
		if (reinterpret_cast<bool(*)(const AActor*, AActor*, AActor*, const FVector&)>(Actor->VFTable[Offsets::IsNetRelevantFor])(
			Actor, ConnectionViewers[viewerIdx].InViewer, ConnectionViewers[viewerIdx].ViewTarget, ConnectionViewers[viewerIdx].ViewLocation))
		{
			return true;
		}
	}

	return false;
}

static FORCEINLINE UNetConnection* IsActorOwnedByAndRelevantToConnection(const AActor* Actor, const std::vector<FNetViewer>& ConnectionViewers, bool& bOutHasNullViewTarget)
{
	const AActor* ActorOwner = Actor->GetNetOwner();

	bOutHasNullViewTarget = false;

	for (int i = 0; i < ConnectionViewers.size(); i++)
	{
		UNetConnection* ViewerConnection = ConnectionViewers[i].Connection;

		auto ViewTarget = ViewerConnection->GetViewTarget();

		if (ViewTarget == nullptr)
		{
			bOutHasNullViewTarget = true;
		}

		if (ActorOwner == ViewerConnection->GetPlayerController() ||
			(ViewerConnection->GetPlayerController() && ActorOwner == ViewerConnection->GetPlayerController()->GetPawn()) ||
			(ViewTarget && ViewTarget->IsRelevancyOwnerFor(Actor, ActorOwner, ViewerConnection->GetOwningActor())))
		{
			return ViewerConnection;
		}
	}

	return nullptr;
}

static FORCEINLINE bool IsActorDormant(FNetworkObjectInfo* ActorInfo, const TWeakObjectPtr<UNetConnection>& Connection)
{
	return ActorInfo->DormantConnections.Contains(Connection);
}

static FORCEINLINE bool ShouldActorGoDormant(AActor* Actor, const std::vector<FNetViewer>& ConnectionViewers, UActorChannel* Channel, const float Time, const bool bLowNetBandwidth)
{
	if (Actor->NetDormancy() <= ENetDormancy::DORM_Awake || !Channel || Channel->IsPendingDormancy() || Channel->IsDormant())
	{
		return false;
	}

	if (Actor->NetDormancy() == ENetDormancy::DORM_DormantPartial)
	{
		for (int32 viewerIdx = 0; viewerIdx < ConnectionViewers.size(); viewerIdx++)
		{
			if (!Actor->GetNetDormancy(ConnectionViewers[viewerIdx].ViewLocation, ConnectionViewers[viewerIdx].ViewDir, ConnectionViewers[viewerIdx].InViewer, ConnectionViewers[viewerIdx].ViewTarget, Channel, Time, bLowNetBandwidth))
			{
				return false;
			}
		}
	}

	return true;
}

int32 UNetDriver::ServerReplicateActors_PrepConnections()
{
	int32 NumClientsToTick = GetClientConnections().Num();

	/*
	static bool bForceClientTickingThrottle = false;
	if (bForceClientTickingThrottle 
		// || GetNetMode() == NM_ListenServer
		)
	{
		static float DeltaTimeOverflow = 0.f;

		static bool LanPlay = false; // FParse::Param(FCommandLine::Get(), TEXT("lanplay"));
		float ClientUpdatesThisFrame = GetEngine()->NetClientTicksPerSecond * (DeltaSeconds + DeltaTimeOverflow) * (LanPlay ? 2.f : 1.f);
		NumClientsToTick = FMath::Min<int32>(NumClientsToTick, FMath::TruncToInt(ClientUpdatesThisFrame));
		if (NumClientsToTick == 0)
		{
			DeltaTimeOverflow += DeltaSeconds;
			return 0;
		}
		DeltaTimeOverflow = 0.f;
	}

	if (NetCmds::MaxConnectionsToTickPerServerFrame->GetInt() > 0)
	{
		NumClientsToTick = FMath::Min(ClientConnections.Num(), NetCmds::MaxConnectionsToTickPerServerFrame->GetInt());
	}
	*/

	bool bFoundReadyConnection = false;

	for (int32 ConnIdx = 0; ConnIdx < GetClientConnections().Num(); ConnIdx++)
	{
		UNetConnection* Connection = GetClientConnections().at(ConnIdx);
		// check(Connection);
		// check(Connection->State == USOCK_Pending || Connection->State == USOCK_Open || Connection->State == USOCK_Closed);
		// checkSlow(Connection->GetUChildConnection() == NULL);

		AActor* OwningActor = Connection->GetOwningActor();
		if (OwningActor != NULL 
			// && Connection->State == USOCK_Open 
			// && (Connection->GetDriver()->Time - Connection->LastReceiveTime < 1.5f)
			)
		{
			// check(World == OwningActor->GetWorld());

			bFoundReadyConnection = true;

			AActor* DesiredViewTarget = OwningActor;
			if (Connection->GetPlayerController())
			{
				if (AActor* ViewTarget = Connection->GetPlayerController()->GetViewTarget())
				{
					if (GetWorld()
						// ViewTarget->GetWorld() // T(REP)
						)
					{
						// It is safe to use the player controller's view target.
						DesiredViewTarget = ViewTarget;
					}
					else
					{

					}
				}
			}
			Connection->GetViewTarget() = DesiredViewTarget;

			for (int32 ChildIdx = 0; ChildIdx < Connection->GetChildren().Num(); ChildIdx++)
			{
				UNetConnection* Child = Connection->GetChildren().at(ChildIdx);
				APlayerController* ChildPlayerController = Child->GetPlayerController();
				if (ChildPlayerController != NULL)
				{
					Child->GetViewTarget() = ChildPlayerController->GetViewTarget();
				}
				else
				{
					Child->GetViewTarget() = NULL;
				}
			}
		}
		else
		{
			Connection->GetViewTarget() = NULL;
			for (int32 ChildIdx = 0; ChildIdx < Connection->GetChildren().Num(); ChildIdx++)
			{
				Connection->GetChildren().at(ChildIdx)->GetViewTarget() = NULL;
			}
		}
	}

	return bFoundReadyConnection ? NumClientsToTick : 0;
}

void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList, const float ServerTickTime)
{
	int32 NumInitiallyDormant = 0;

	const bool bUseAdapativeNetFrequency = true; // IsAdaptiveNetUpdateFrequencyEnabled(); // T(REP)

	std::vector<AActor*> ActorsToRemove;

	for (const TSharedPtr<FNetworkObjectInfo>& ObjectInfo : GetNetworkObjectList().GetActiveObjects())
	{
		FNetworkObjectInfo* ActorInfo = ObjectInfo.Get();

		if (!ActorInfo->bPendingNetUpdate && World()->GetTimeSeconds() <= ActorInfo->NextUpdateTime)
		{
			continue;
		}

		AActor* Actor = ActorInfo->Actor;

		if (Actor->IsPendingKillPending())
		{
			ActorsToRemove.push_back(Actor);
			continue;
		}

		if (Actor->GetRemoteRole() == ROLE_None)
		{
			ActorsToRemove.push_back(Actor);
			continue;
		}

		if (Actor->GetNetDriverName() != this->GetNetDriverName()) // Milxnor: This really shouldn't happen on Fortnite.
		{
			continue;
		}

		if (!Actor->IsActorInitialized())
		{
			continue;
		}

		ULevel* Level = Actor->GetLevel();
		if (Level->HasVisibilityChangeRequestPending() || Level->IsAssociatingLevel())
		{
			continue;
		}

		if (Actor->NetDormancy() == ENetDormancy::DORM_Initial && Actor->IsNetStartupActor())
		{
			NumInitiallyDormant++;
			ActorsToRemove.push_back(Actor);
			continue;
		}

		// checkSlow(Actor->NeedsLoadForClient()); // We have no business sending this unless the client can load
		// checkSlow(World() == Actor->GetWorld());

		if (ActorInfo->LastNetReplicateTime == 0)
		{
			ActorInfo->LastNetReplicateTime = World()->GetTimeSeconds();
			ActorInfo->OptimalNetUpdateDelta = 1.0f / Actor->GetNetUpdateFrequency();
		}

		const float ScaleDownStartTime = 2.0f;
		const float ScaleDownTimeRange = 5.0f;

		const float LastReplicateDelta = World()->GetTimeSeconds() - ActorInfo->LastNetReplicateTime;

		if (LastReplicateDelta > ScaleDownStartTime)
		{
			if (Actor->GetMinNetUpdateFrequency() == 0.0f)
			{
				Actor->GetMinNetUpdateFrequency() = 2.0f;
			}

			const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency();									 
			const float MaxOptimalDelta = FMath::Max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta);

			const float Alpha = FMath::Clamp((LastReplicateDelta - ScaleDownStartTime) / ScaleDownTimeRange, 0.0f, 1.0f);
			ActorInfo->OptimalNetUpdateDelta = FMath::Lerp(MinOptimalDelta, MaxOptimalDelta, Alpha);
		}

		if (!ActorInfo->bPendingNetUpdate)
		{
			const float NextUpdateDelta = bUseAdapativeNetFrequency ? ActorInfo->OptimalNetUpdateDelta : 1.0f / Actor->GetNetUpdateFrequency();
			ActorInfo->NextUpdateTime = World()->GetTimeSeconds() + FMath::SRand() * ServerTickTime + NextUpdateDelta;
			ActorInfo->LastNetUpdateTime = GetTime();
		}

		ActorInfo->bPendingNetUpdate = false;

		// ensure(OutConsiderList.Num() < OutConsiderList.Max());
		OutConsiderList.push_back(ActorInfo);

		// Call PreReplication on all actors that will be considered
		AActor::originalCallPreReplication(Actor, this);
	}

	for (AActor* Actor : ActorsToRemove)
	{
		GetNetworkObjectList().Remove(Actor);
	}
}

int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, const std::vector<FNetworkObjectInfo*>& ConsiderList, const bool bCPUSaturated, std::vector<FActorPriority>& OutPriorityList, std::vector<FActorPriority*>& OutPriorityActors)
{
	GetNetTag()++;
	Connection->GetTickCount()++;

	// Set up to skip all sent temporary actors
	for (int32 j = 0; j < Connection->GetSentTemporaries().Num(); j++)
	{
		Connection->GetSentTemporaries().at(j)->GetNetTag() = GetNetTag();
	}

	// Make list of all actors to consider.
	// check(World() == Connection->GetOwningActor()->GetWorld());

	int32 FinalSortedCount = 0;
	int32 DeletedCount = 0;

	// Make weak ptr once for IsActorDormant call
	TWeakObjectPtr<UNetConnection> WeakConnection; // T(REP)
	WeakConnection.ObjectIndex = Connection->InternalIndex;
	WeakConnection.ObjectSerialNumber = GetItemByIndex(Connection->InternalIndex)->SerialNumber;

	const int32 MaxSortedActors = ConsiderList.size() + GetDestroyedStartupOrDormantActors().Num();
	if (MaxSortedActors > 0)
	{
		// OutPriorityList = new (FMemStack::Get(), MaxSortedActors) FActorPriority;
		// OutPriorityActors = new (FMemStack::Get(), MaxSortedActors) FActorPriority*;
		OutPriorityList.reserve(MaxSortedActors);
		OutPriorityActors.reserve(MaxSortedActors);

		// check(World() == Connection->GetViewTarget()->GetWorld());

		// AGameNetworkManager* const NetworkManager = World->NetworkManager;
		const bool bLowNetBandwidth = false; // NetworkManager ? NetworkManager->IsInLowBandwidthMode() : false; // Milxnor: Again, this really shouldn't be needed.

		for (FNetworkObjectInfo* ActorInfo : ConsiderList)
		{
			AActor* Actor = ActorInfo->Actor;

			UActorChannel* Channel = Connection->GetActorChannels().FindRef(ActorInfo->WeakActor);

			if (!Channel)
			{
				if (!IsLevelInitializedForActor(Actor, Connection))
				{
					continue;
				}

				if (!IsActorRelevantToConnection(Actor, ConnectionViewers))
				{
					continue;
				}
			}

			UNetConnection* PriorityConnection = Connection;

			if (Actor->IsOnlyRelevantToOwner())
			{
				bool bHasNullViewTarget = false;

				PriorityConnection = IsActorOwnedByAndRelevantToConnection(Actor, ConnectionViewers, bHasNullViewTarget);

				if (PriorityConnection == nullptr)
				{
					if (!bHasNullViewTarget && Channel != NULL && GetTime() - Channel->GetRelevantTime() >= GetRelevantTimeout())
					{
						Channel->Close();
					}

					continue;
				}
			}
			else if (// CVarSetNetDormancyEnabled.GetValueOnGameThread() != 0 // Milxnor: This is always enabled no?
				true)
			{
				if (IsActorDormant(ActorInfo, WeakConnection))
				{
					continue;
				}

				if (ShouldActorGoDormant(Actor, ConnectionViewers, Channel, GetTime(), bLowNetBandwidth))
				{
					Channel->StartBecomingDormant();
				}
			}

			if (Actor->GetNetTag() != GetNetTag())
			{
				Actor->GetNetTag() = GetNetTag();

				OutPriorityList[FinalSortedCount] = FActorPriority(PriorityConnection, Channel, ActorInfo, ConnectionViewers, bLowNetBandwidth);
				// OutPriorityActors[FinalSortedCount] = OutPriorityList + FinalSortedCount;

				FinalSortedCount++;
			}
		}

		// Add in deleted actors
		for (auto It = Connection->GetDestroyedStartupOrDormantActors().CreateIterator(); It; ++It)
		{
			FActorDestructionInfo& DInfo = GetDestroyedStartupOrDormantActors().FindChecked(*It);
			OutPriorityList[FinalSortedCount] = FActorPriority(Connection, &DInfo, ConnectionViewers);
			OutPriorityActors[FinalSortedCount] = OutPriorityList.data() + FinalSortedCount;
			FinalSortedCount++;
			DeletedCount++;
		}

		// Sort(OutPriorityActors, FinalSortedCount, FCompareFActorPriority());
	}

	return FinalSortedCount;
}

int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection* Connection, const std::vector<FNetViewer>& ConnectionViewers, std::vector<FActorPriority*>& PriorityActors, const int32 FinalSortedCount, int32& OutUpdated)
{
	int32 ActorUpdatesThisConnection = 0;
	int32 ActorUpdatesThisConnectionSent = 0;
	int32 FinalRelevantCount = 0;

	if (!Connection->IsNetReady(0))
	{
		return 0;
	}

	for (int32 j = 0; j < FinalSortedCount; j++)
	{
		FNetworkObjectInfo* ActorInfo = PriorityActors[j]->ActorInfo;

		// Deletion entry
		if (ActorInfo == NULL && PriorityActors[j]->DestructionInfo)
		{
			/*
			if (PriorityActors[j]->DestructionInfo->StreamingLevelName != NAME_None && 
				!Connection->GetClientVisibleLevelNames().Contains(PriorityActors[j]->DestructionInfo->StreamingLevelName)
				)
			{
				continue;
			}

			UActorChannel* Channel = (UActorChannel*)Connection->CreateChannel(CHTYPE_Actor, 1, EChannelCreateFlags::OpenedLocally);
			if (Channel)
			{
				FinalRelevantCount++;

				Channel->SetChannelActorForDestroy(PriorityActors[j]->DestructionInfo);
				Connection->GetDestroyedStartupOrDormantActors().Remove(PriorityActors[j]->DestructionInfo->NetGUID);
			}

			*/

			continue;
		}

		UActorChannel* Channel = PriorityActors[j]->Channel;
		if (!Channel || Channel->GetActor())
		{
			AActor* Actor = ActorInfo->Actor;
			bool bIsRelevant = false;

			const bool bLevelInitializedForActor = IsLevelInitializedForActor(Actor, Connection);

			if (bLevelInitializedForActor)
			{
				if (!Actor->IsTearOff() && (!Channel || GetTime() - Channel->GetRelevantTime() > 1.f))
				{
					if (IsActorRelevantToConnection(Actor, ConnectionViewers))
					{
						bIsRelevant = true;
					}
				}
			}

			// if the actor is now relevant or was recently relevant
			const bool bIsRecentlyRelevant = bIsRelevant || (Channel && GetTime() - Channel->GetRelevantTime() < GetRelevantTimeout()) || ActorInfo->bForceRelevantNextUpdate;

			ActorInfo->bForceRelevantNextUpdate = false;

			if (bIsRecentlyRelevant)
			{
				FinalRelevantCount++;

				if (Channel == NULL 
					// T(REP)
					// && GuidCache->SupportsObject(Actor->GetClass()) 
					// && GuidCache->SupportsObject(Actor->IsNetStartupActor() ? Actor : Actor->GetArchetype())
					)
				{
					if (bLevelInitializedForActor)
					{
						Channel = (UActorChannel*)Connection->CreateChannel(CHTYPE_Actor, 1, EChannelCreateFlags::OpenedLocally);
						if (Channel)
						{
							Channel->SetChannelActor(Actor, ESetChannelActorFlags::None1);
						}
					}
					else if (Actor->GetNetUpdateFrequency() < 1.0f)
					{
						auto ActorWorld = GetWorld(); // Actor->GetWorld() // T(REP)
						ActorInfo->NextUpdateTime = ActorWorld->GetTimeSeconds() + 0.2f * FMath::FRand();
					}
				}

				if (Channel)
				{
					if (bIsRelevant)
					{
						Channel->GetRelevantTime() = GetTime() + 0.5f * FMath::SRand();
					}
					if (Channel->IsNetReady(0))
					{
						if (Channel->ReplicateActor())
						{
							ActorUpdatesThisConnectionSent++;

							const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency();
							const float MaxOptimalDelta = FMath::Max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta);
							const float DeltaBetweenReplications = (World()->GetTimeSeconds() - ActorInfo->LastNetReplicateTime);

							ActorInfo->OptimalNetUpdateDelta = FMath::Clamp(DeltaBetweenReplications * 0.7f, MinOptimalDelta, MaxOptimalDelta);
							ActorInfo->LastNetReplicateTime = World()->GetTimeSeconds();
						}

						ActorUpdatesThisConnection++;
						OutUpdated++;
					}
					else
					{
						Actor->ForceNetUpdate();
					}

					if (!Connection->IsNetReady(0))
					{
						return j;
					}
				}
			}

			if ((!bIsRecentlyRelevant || Actor->IsTearOff()) && Channel != NULL)
			{
				if (!bLevelInitializedForActor || !Actor->IsNetStartupActor())
				{
					Channel->Close();
				}
			}
		}
	}

	return FinalSortedCount;
}

int32 UNetDriver::ServerReplicateActors()
{
	float DeltaSeconds = 0; // T(REP) Milxnor: This is a parameter but really I cant be asked to implement it.

	/*
	
	if ( ClientConnections.Num() == 0 )
	{
		return 0;
	}

	check( World );

	*/

	int32 Updated = 0;

	// Bump the ReplicationFrame value to invalidate any properties marked as "unchanged" for this frame.
	++(*(int*)(__int64(this) + Offsets::ReplicationFrame));

	const int32 NumClientsToTick = ServerReplicateActors_PrepConnections();

	if (NumClientsToTick == 0)
	{
		// No connections are ready this frame
		return 0;
	}

	AWorldSettings* WorldSettings = World()->GetWorldSettings();

	bool bCPUSaturated = false;
	float ServerTickTime = ServerTickRate; // GetEngine()->GetMaxTickRate(DeltaSeconds); // Milxnor: We hook GetMaxTickRate and just return ServerTickRate.
	if (ServerTickTime == 0.f)
	{
		ServerTickTime = DeltaSeconds;
	}
	else
	{
		ServerTickTime = 1.f / ServerTickTime;
		bCPUSaturated = DeltaSeconds > 1.2f * ServerTickTime;
	}

	std::vector<FNetworkObjectInfo*> ConsiderList;
	ConsiderList.reserve(GetNetworkObjectList().GetActiveObjects().Num());

	// Build the consider list (actors that are ready to replicate)
	ServerReplicateActors_BuildConsiderList(ConsiderList, ServerTickTime);

	for (int32 i = 0; i < GetClientConnections().Num(); ++i)
	{
		UNetConnection* Connection = GetClientConnections().at(i);
		if (!Connection) continue;

		/*
		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 (i >= NumClientsToTick)
		{
			for (int32 ConsiderIdx = 0; ConsiderIdx < ConsiderList.size(); ++ConsiderIdx)
			{
				AActor* Actor = ConsiderList[ConsiderIdx]->Actor;

				if (Actor != NULL && !ConsiderList[ConsiderIdx]->bPendingNetUpdate)
				{
					UActorChannel* Channel = Connection->GetActorChannels().FindRef(ConsiderList[ConsiderIdx]->WeakActor);

					if (Channel != NULL && Channel->GetLastUpdateTime() < ConsiderList[ConsiderIdx]->LastNetUpdateTime)
					{
						ConsiderList[ConsiderIdx]->bPendingNetUpdate = true;
					}
				}
			}

			// Connection->GetTimeSensitive() = false;
		}
		else if (Connection->GetViewTarget())
		{
			// std::vector<FNetViewer>& ConnectionViewers = WorldSettings->GetReplicationViewers(); // Milxnor: Techinally this is proper but they literally just reset it before rep ends.
			std::vector<FNetViewer> ConnectionViewers;
			ConnectionViewers.clear();

			// new(ConnectionViewers)FNetViewer(Connection, DeltaSeconds);
			ConnectionViewers.push_back(FNetViewer(Connection, DeltaSeconds));

			for (int32 ViewerIndex = 0; ViewerIndex < Connection->GetChildren().Num(); ++ViewerIndex)
			{
				if (Connection->GetChildren().at(ViewerIndex)->GetViewTarget() != NULL)
				{
					// new(ConnectionViewers)FNetViewer(Connection->GetChildren().at(ViewerIndex), DeltaSeconds);
					ConnectionViewers.push_back(FNetViewer(Connection->GetChildren().at(ViewerIndex), DeltaSeconds));
				}
			}

			if (Connection->GetPlayerController())
			{
				APlayerController::originalSendClientAdjustment(Connection->GetPlayerController());
			}

			for (int32 ChildIdx = 0; ChildIdx < Connection->GetChildren().Num(); ChildIdx++)
			{
				if (Connection->GetChildren().at(ChildIdx)->GetPlayerController() != NULL)
				{
					APlayerController::originalSendClientAdjustment(Connection->GetChildren().at(ChildIdx)->GetPlayerController());
				}
			}

			std::vector<FActorPriority> PriorityList;
			std::vector<FActorPriority*> PriorityActors;

			const int32 FinalSortedCount = ServerReplicateActors_PrioritizeActors(Connection, ConnectionViewers, ConsiderList, bCPUSaturated, PriorityList, PriorityActors);

			// Process the sorted list of actors for this connection
			const int32 LastProcessedActor = ServerReplicateActors_ProcessPrioritizedActors(Connection, ConnectionViewers, PriorityActors, FinalSortedCount, Updated);

			for (int32 k = LastProcessedActor; k < FinalSortedCount; ++k)
			{
				if (!PriorityActors[k]->ActorInfo)
				{
					continue;
				}

				AActor* Actor = PriorityActors[k]->ActorInfo->Actor;

				UActorChannel* Channel = PriorityActors[k]->Channel;

				if (Channel != NULL && GetTime() - Channel->GetRelevantTime() <= 1.f)
				{
					PriorityActors[k]->ActorInfo->bPendingNetUpdate = true;
				}
				else if (IsActorRelevantToConnection(Actor, ConnectionViewers))
				{
					PriorityActors[k]->ActorInfo->bPendingNetUpdate = true;
					if (Channel != NULL)
					{
						Channel->GetRelevantTime() = GetTime() + 0.5f * FMath::SRand();
					}
				}
			}

			ConnectionViewers.clear();
		}
	}

	return Updated;
}