You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* For AlwaysRelevant actors we will now always send the DestructionInfo to connections that knew of this actor. * Added a flag to FActorDestructionInfo that ignores the distance culling test. [RN] minor engine/network #rb Ryan.Gerleve #ROBOMERGE-SOURCE: CL 10802164 via CL 10802173 via CL 10802516 via CL 10802550 via CL 10802580 #ROBOMERGE-BOT: (v610-10636431) [CL 10802634 by louisphilippe seguin in Main branch]
200 lines
6.2 KiB
C++
200 lines
6.2 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
//
|
|
#include "BasicReplicationGraph.h"
|
|
#include "Net/UnrealNetwork.h"
|
|
#include "Engine/LevelStreaming.h"
|
|
#include "EngineUtils.h"
|
|
#include "CoreGlobals.h"
|
|
#include "UObject/UObjectIterator.h"
|
|
#include "Engine/NetConnection.h"
|
|
#include "Engine/ChildConnection.h"
|
|
|
|
UBasicReplicationGraph::UBasicReplicationGraph()
|
|
{
|
|
|
|
}
|
|
|
|
void UBasicReplicationGraph::InitGlobalActorClassSettings()
|
|
{
|
|
Super::InitGlobalActorClassSettings();
|
|
|
|
// ReplicationGraph stores internal associative data for actor classes.
|
|
// We build this data here based on actor CDO values.
|
|
for (TObjectIterator<UClass> It; It; ++It)
|
|
{
|
|
UClass* Class = *It;
|
|
AActor* ActorCDO = Cast<AActor>(Class->GetDefaultObject());
|
|
if (!ActorCDO || !ActorCDO->GetIsReplicated())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Skip SKEL and REINST classes.
|
|
if (Class->GetName().StartsWith(TEXT("SKEL_")) || Class->GetName().StartsWith(TEXT("REINST_")))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
FClassReplicationInfo ClassInfo;
|
|
|
|
// Replication Graph is frame based. Convert NetUpdateFrequency to ReplicationPeriodFrame based on Server MaxTickRate.
|
|
ClassInfo.ReplicationPeriodFrame = GetReplicationPeriodFrameForFrequency(ActorCDO->NetUpdateFrequency);
|
|
|
|
if (ActorCDO->bAlwaysRelevant || ActorCDO->bOnlyRelevantToOwner)
|
|
{
|
|
ClassInfo.SetCullDistanceSquared(0.f);
|
|
}
|
|
else
|
|
{
|
|
ClassInfo.SetCullDistanceSquared(ActorCDO->NetCullDistanceSquared);
|
|
}
|
|
|
|
GlobalActorReplicationInfoMap.SetClassInfo( Class, ClassInfo );
|
|
}
|
|
}
|
|
|
|
void UBasicReplicationGraph::InitGlobalGraphNodes()
|
|
{
|
|
// Preallocate some replication lists.
|
|
PreAllocateRepList(3, 12);
|
|
PreAllocateRepList(6, 12);
|
|
PreAllocateRepList(128, 64);
|
|
|
|
// -----------------------------------------------
|
|
// Spatial Actors
|
|
// -----------------------------------------------
|
|
|
|
GridNode = CreateNewNode<UReplicationGraphNode_GridSpatialization2D>();
|
|
GridNode->CellSize = 10000.f;
|
|
GridNode->SpatialBias = FVector2D(-WORLD_MAX, -WORLD_MAX);
|
|
|
|
AddGlobalGraphNode(GridNode);
|
|
|
|
// -----------------------------------------------
|
|
// Always Relevant (to everyone) Actors
|
|
// -----------------------------------------------
|
|
AlwaysRelevantNode = CreateNewNode<UReplicationGraphNode_ActorList>();
|
|
AddGlobalGraphNode(AlwaysRelevantNode);
|
|
}
|
|
|
|
void UBasicReplicationGraph::InitConnectionGraphNodes(UNetReplicationGraphConnection* RepGraphConnection)
|
|
{
|
|
Super::InitConnectionGraphNodes(RepGraphConnection);
|
|
|
|
UReplicationGraphNode_AlwaysRelevant_ForConnection* AlwaysRelevantNodeForConnection = CreateNewNode<UReplicationGraphNode_AlwaysRelevant_ForConnection>();
|
|
AddConnectionGraphNode(AlwaysRelevantNodeForConnection, RepGraphConnection);
|
|
|
|
AlwaysRelevantForConnectionList.Emplace(RepGraphConnection->NetConnection, AlwaysRelevantNodeForConnection);
|
|
}
|
|
|
|
void UBasicReplicationGraph::RouteAddNetworkActorToNodes(const FNewReplicatedActorInfo& ActorInfo, FGlobalActorReplicationInfo& GlobalInfo)
|
|
{
|
|
if (ActorInfo.Actor->bAlwaysRelevant)
|
|
{
|
|
AlwaysRelevantNode->NotifyAddNetworkActor(ActorInfo);
|
|
}
|
|
else if (ActorInfo.Actor->bOnlyRelevantToOwner)
|
|
{
|
|
ActorsWithoutNetConnection.Add(ActorInfo.Actor);
|
|
}
|
|
else
|
|
{
|
|
// Note that UReplicationGraphNode_GridSpatialization2D has 3 methods for adding actor based on the mobility of the actor. Since AActor lacks this information, we will
|
|
// add all spatialized actors as dormant actors: meaning they will be treated as possibly dynamic (moving) when not dormant, and as static (not moving) when dormant.
|
|
GridNode->AddActor_Dormancy(ActorInfo, GlobalInfo);
|
|
}
|
|
}
|
|
|
|
void UBasicReplicationGraph::RouteRemoveNetworkActorToNodes(const FNewReplicatedActorInfo& ActorInfo)
|
|
{
|
|
if (ActorInfo.Actor->bAlwaysRelevant)
|
|
{
|
|
AlwaysRelevantNode->NotifyRemoveNetworkActor(ActorInfo);
|
|
SetActorDestructionInfoToIgnoreDistanceCulling(ActorInfo.GetActor());
|
|
}
|
|
else if (ActorInfo.Actor->bOnlyRelevantToOwner)
|
|
{
|
|
if (UReplicationGraphNode* Node = ActorInfo.Actor->GetNetConnection() ? GetAlwaysRelevantNodeForConnection(ActorInfo.Actor->GetNetConnection()) : nullptr)
|
|
{
|
|
Node->NotifyRemoveNetworkActor(ActorInfo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GridNode->RemoveActor_Dormancy(ActorInfo);
|
|
}
|
|
}
|
|
|
|
UReplicationGraphNode_AlwaysRelevant_ForConnection* UBasicReplicationGraph::GetAlwaysRelevantNodeForConnection(UNetConnection* Connection)
|
|
{
|
|
UReplicationGraphNode_AlwaysRelevant_ForConnection* Node = nullptr;
|
|
if (Connection)
|
|
{
|
|
if (FConnectionAlwaysRelevantNodePair* Pair = AlwaysRelevantForConnectionList.FindByKey(Connection))
|
|
{
|
|
if (Pair->Node)
|
|
{
|
|
Node = Pair->Node;
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogNet, Warning, TEXT("AlwaysRelevantNode for connection %s is null."), *GetNameSafe(Connection));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogNet, Warning, TEXT("Could not find AlwaysRelevantNode for connection %s. This should have been created in UBasicReplicationGraph::InitConnectionGraphNodes."), *GetNameSafe(Connection));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Basic implementation requires owner is set on spawn that never changes. A more robust graph would have methods or ways of listening for owner to change
|
|
UE_LOG(LogNet, Warning, TEXT("Actor: %s is bOnlyRelevantToOwner but does not have an owning Netconnection. It will not be replicated"));
|
|
}
|
|
|
|
return Node;
|
|
}
|
|
|
|
int32 UBasicReplicationGraph::ServerReplicateActors(float DeltaSeconds)
|
|
{
|
|
// Route Actors needing owning net connections to appropriate nodes
|
|
for (int32 idx=ActorsWithoutNetConnection.Num()-1; idx>=0; --idx)
|
|
{
|
|
bool bRemove = false;
|
|
if (AActor* Actor = ActorsWithoutNetConnection[idx])
|
|
{
|
|
if (UNetConnection* Connection = Actor->GetNetConnection())
|
|
{
|
|
bRemove = true;
|
|
if (UReplicationGraphNode_AlwaysRelevant_ForConnection* Node = GetAlwaysRelevantNodeForConnection(Actor->GetNetConnection()))
|
|
{
|
|
Node->NotifyAddNetworkActor(FNewReplicatedActorInfo(Actor));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bRemove = true;
|
|
}
|
|
|
|
if (bRemove)
|
|
{
|
|
ActorsWithoutNetConnection.RemoveAtSwap(idx, 1, false);
|
|
}
|
|
}
|
|
|
|
|
|
return Super::ServerReplicateActors(DeltaSeconds);
|
|
}
|
|
|
|
bool FConnectionAlwaysRelevantNodePair::operator==(UNetConnection* InConnection) const
|
|
{
|
|
// Any children should be looking at their parent connections instead.
|
|
if (InConnection->GetUChildConnection() != nullptr)
|
|
{
|
|
InConnection = ((UChildConnection*)InConnection)->Parent;
|
|
}
|
|
|
|
return InConnection == NetConnection;
|
|
}
|