ULevel* CreateNewLevel( UWorld* InWorld, bool bMoveSelectedActorsIntoNewLevel, UClass* LevelStreamingClass, const FString& DefaultFilename )
{
    // Editor modes cannot be active when any level saving occurs.
    GEditorModeTools().ActivateMode( FBuiltinEditorModes::EM_Default );

    // Create a new world - so we can 'borrow' its level
    UWorld* NewGWorld = UWorld::CreateWorld(EWorldType::None, false );
    check(NewGWorld);

    // Save the new world to disk.
    const bool bNewWorldSaved = FEditorFileUtils::SaveLevel( NewGWorld->PersistentLevel, DefaultFilename );
    FString NewPackageName;
    if ( bNewWorldSaved )
    {
        NewPackageName = NewGWorld->GetOutermost()->GetName();
    }

    // Destroy the new world we created and collect the garbage
    NewGWorld->DestroyWorld( false );
    CollectGarbage( GARBAGE_COLLECTION_KEEPFLAGS );

    // If the new world was saved successfully, import it as a streaming level.
    ULevel* NewLevel = NULL;
    if ( bNewWorldSaved )
    {
        NewLevel = AddLevelToWorld( InWorld, *NewPackageName, LevelStreamingClass );

        // If we are moving the selected actors to the new level move them now
        if ( bMoveSelectedActorsIntoNewLevel )
        {
            GEditor->MoveSelectedActorsToLevel( NewLevel );
        }
        // Finally make the new level the current one
        InWorld->SetCurrentLevel( NewLevel );
    }

    // Broadcast the levels have changed (new style)
    InWorld->BroadcastLevelsChanged();
    return NewLevel;
}
void FWorldTileModel::AddStreamingLevel(UClass* InStreamingClass, const FName& InPackageName)
{
	if (LevelCollectionModel.IsReadOnly() || !IsEditable() || IsRootTile())
	{
		return;
	}

	UWorld* LevelWorld = CastChecked<UWorld>(GetLevelObject()->GetOuter());
	// check uniqueness 
	if (LevelWorld->StreamingLevels.FindMatch(ULevelStreaming::FPackageNameMatcher(InPackageName)) != INDEX_NONE)
	{
		return;
	}
		
	ULevelStreaming* StreamingLevel = static_cast<ULevelStreaming*>(StaticConstructObject(InStreamingClass, LevelWorld, NAME_None, RF_NoFlags, NULL));
	// Associate a package name.
	StreamingLevel->PackageName			= InPackageName;
	// Seed the level's draw color.
	StreamingLevel->DrawColor			= FColor::MakeRandomColor();
	StreamingLevel->LevelTransform		= FTransform::Identity;
	StreamingLevel->PackageNameToLoad	= InPackageName;

	// Add the streaming level to level's world
	LevelWorld->StreamingLevels.Add(StreamingLevel);
	LevelWorld->GetOutermost()->MarkPackageDirty();
}
Beispiel #3
0
void ANUTActor::ServerClientPing_Implementation()
{
	// If any clients have not loaded the current level, do nothing
	bool bNotLoaded = false;

	UWorld* CurWorld = GetWorld();
	UNetDriver* CurNetDriver = (CurWorld != NULL ? NUTUtil::GetActiveNetDriver(CurWorld) : NULL);

	for (auto CurConn : CurNetDriver->ClientConnections)
	{
		// Based on UNetDriver::IsLevelInitializeForActor
		bNotLoaded = !(CurConn->ClientWorldPackageName == CurWorld->GetOutermost()->GetFName() &&
									CurConn->ClientHasInitializedLevelFor(this));

		// Also trigger if there is no PlayerController yet set for the connection
		if (CurConn->OwningActor == NULL)
		{
			bNotLoaded = true;
		}


		if (bNotLoaded)
		{
			break;
		}
	}

	if (!bNotLoaded)
	{
		NetMulticastPing();
	}
}
void AOnlineBeaconHost::NotifyControlMessage(UNetConnection* Connection, uint8 MessageType, class FInBunch& Bunch)
{
    if(NetDriver->ServerConnection == NULL)
    {
        bool bCloseConnection = false;

        // We are the server.
#if !(UE_BUILD_SHIPPING && WITH_EDITOR)
        UE_LOG(LogNet, Verbose, TEXT("Beacon: Host received: %s"), FNetControlMessageInfo::GetName(MessageType));
#endif
        switch (MessageType)
        {
        case NMT_Hello:
        {
            UE_LOG(LogNet, Log, TEXT("Beacon Hello"));
            uint8 IsLittleEndian;
            int32 RemoteMinVer, RemoteVer;
            FGuid RemoteGameGUID;
            FNetControlMessage<NMT_Hello>::Receive(Bunch, IsLittleEndian, RemoteMinVer, RemoteVer, RemoteGameGUID);

            if (!IsNetworkCompatible(Connection->Driver->RequireEngineVersionMatch, RemoteVer, RemoteMinVer))
            {
                FNetControlMessage<NMT_Upgrade>::Send(Connection, GEngineMinNetVersion, GEngineNetVersion);
                bCloseConnection = true;
            }
            else
            {
                Connection->NegotiatedVer = FMath::Min(RemoteVer, GEngineNetVersion);

                // Make sure the server has the same GameGUID as we do
                if( RemoteGameGUID != GetDefault<UGeneralProjectSettings>()->ProjectID )
                {
                    FString ErrorMsg = NSLOCTEXT("NetworkErrors", "ServerHostingDifferentGame", "Incompatible game connection.").ToString();
                    FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg);
                    bCloseConnection = true;
                    break;
                }

                Connection->Challenge = FString::Printf(TEXT("%08X"), FPlatformTime::Cycles());
                FNetControlMessage<NMT_BeaconWelcome>::Send(Connection);
                Connection->FlushNet();
            }
            break;
        }
        case NMT_Netspeed:
        {
            int32 Rate;
            FNetControlMessage<NMT_Netspeed>::Receive(Bunch, Rate);
            Connection->CurrentNetSpeed = FMath::Clamp(Rate, 1800, NetDriver->MaxClientRate);
            UE_LOG(LogNet, Log, TEXT("Beacon: Client netspeed is %i"), Connection->CurrentNetSpeed);
            break;
        }
        case NMT_BeaconJoin:
        {
            FString ErrorMsg;
            FString BeaconType;
            FNetControlMessage<NMT_BeaconJoin>::Receive(Bunch, BeaconType);
            UE_LOG(LogNet, Log, TEXT("Beacon Join %s"), *BeaconType);

            if (Connection->ClientWorldPackageName == NAME_None)
            {
                AOnlineBeaconClient* ClientActor = GetClientActor(Connection);
                if (ClientActor == NULL)
                {
                    UWorld* World = GetWorld();
                    Connection->ClientWorldPackageName = World->GetOutermost()->GetFName();

                    AOnlineBeaconClient* NewClientActor = SpawnBeaconActor();
                    if (NewClientActor && BeaconType == NewClientActor->GetBeaconType())
                    {
                        FNetworkGUID NetGUID = Connection->PackageMap->AssignNewNetGUID(NewClientActor);
                        NewClientActor->SetNetConnection(Connection);
                        Connection->OwningActor = NewClientActor;
                        NewClientActor->Role = ROLE_None;
                        NewClientActor->SetReplicates(false);
                        ClientActors.Add(NewClientActor);
                        FNetControlMessage<NMT_BeaconAssignGUID>::Send(Connection, NetGUID);
                    }
                    else
                    {
                        ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnFailureError", "Join failure, Couldn't spawn beacon.").ToString();
                    }
                }
                else
                {
                    ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnExistingActorError", "Join failure, existing beacon actor.").ToString();;
                }
            }
            else
            {
                ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnClientWorldPackageNameError", "Join failure, existing ClientWorldPackageName.").ToString();;
            }

            if (!ErrorMsg.IsEmpty())
            {
                UE_LOG(LogNet, Log, TEXT("%s"), *ErrorMsg);
                FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg);
                bCloseConnection = true;
            }

            break;
        }
        case NMT_BeaconNetGUIDAck:
        {
            FString BeaconType;
            FNetControlMessage<NMT_BeaconNetGUIDAck>::Receive(Bunch, BeaconType);

            AOnlineBeaconClient* ClientActor = GetClientActor(Connection);
            if (ClientActor && BeaconType == ClientActor->GetBeaconType())
            {
                ClientActor->Role = ROLE_Authority;
                ClientActor->SetReplicates(true);
                ClientActor->SetAutonomousProxy(true);
                // Send an RPC to the client to open the actor channel and guarantee RPCs will work
                ClientActor->ClientOnConnected();
                UE_LOG(LogNet, Log, TEXT("Beacon Handshake complete!"));
                FOnBeaconConnected* OnBeaconConnectedDelegate = OnBeaconConnectedMapping.Find(FName(*BeaconType));
                if (OnBeaconConnectedDelegate)
                {
                    OnBeaconConnectedDelegate->ExecuteIfBound(ClientActor, Connection);
                }
            }
            else
            {
                // Failed to connect.
                FString ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnNetGUIDAckError", "Join failure, no actor at NetGUIDAck.").ToString();
                UE_LOG(LogNet, Log, TEXT("%s"), *ErrorMsg);
                FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg);
                bCloseConnection = true;
            }
            break;
        }
        case NMT_BeaconWelcome:
        case NMT_BeaconAssignGUID:
        default:
        {
            FString ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnUnexpectedError", "Join failure, unexpected control message.").ToString();
            UE_LOG(LogNet, Log, TEXT("%s"), *ErrorMsg);
            FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg);
            bCloseConnection = true;
        }
        break;
        }

        if (bCloseConnection)
        {
            AOnlineBeaconClient* ClientActor = GetClientActor(Connection);
            if (ClientActor)
            {
                RemoveClientActor(ClientActor);
            }

            Connection->FlushNet(true);
            Connection->Close();
        }
    }
}
void UWorldComposition::Rescan()
{
	// Save tiles state, so we can restore it for dirty tiles after rescan is done
	FTilesList SavedTileList = Tiles;
		
	Reset();	

	UWorld* OwningWorld = GetWorld();
	
	FString RootPackageName = GetOutermost()->GetName();
	RootPackageName = UWorld::StripPIEPrefixFromPackageName(RootPackageName, OwningWorld->StreamingLevelsPrefix);
	if (!FPackageName::DoesPackageExist(RootPackageName))
	{
		return;	
	}
	
	WorldRoot = FPaths::GetPath(RootPackageName) + TEXT("/");
			
	// Gather tiles packages from a specified folder
	FWorldTilesGatherer Gatherer;
	FString WorldRootFilename = FPackageName::LongPackageNameToFilename(WorldRoot);
	FPlatformFileManager::Get().GetPlatformFile().IterateDirectoryRecursively(*WorldRootFilename, Gatherer);

	// Make sure we have persistent level name without PIE prefix
	FString PersistentLevelPackageName = UWorld::StripPIEPrefixFromPackageName(OwningWorld->GetOutermost()->GetName(), OwningWorld->StreamingLevelsPrefix);
		
	// Add found tiles to a world composition, except persistent level
	for (const auto& TilePackageName : Gatherer.TilesCollection)
	{
		// Discard persistent level entry
		if (TilePackageName == PersistentLevelPackageName)
		{
			continue;
		}

		FWorldTileInfo Info;
		FString TileFilename = FPackageName::LongPackageNameToFilename(TilePackageName, FPackageName::GetMapPackageExtension());
		if (!FWorldTileInfo::Read(TileFilename, Info))
		{
			continue;
		}

		FWorldCompositionTile Tile;
		Tile.PackageName = FName(*TilePackageName);
		Tile.Info = Info;
		
		// Assign LOD tiles
		FString TileShortName = FPackageName::GetShortName(TilePackageName);
		TArray<FPackageNameAndLODIndex> TileLODList;
		Gatherer.TilesLODCollection.MultiFind(TileShortName, TileLODList);
		if (TileLODList.Num())
		{
			Tile.LODPackageNames.SetNum(WORLDTILE_LOD_MAX_INDEX);
			FString TilePath = FPackageName::GetLongPackagePath(TilePackageName) + TEXT("/");
			for (const auto& TileLOD : TileLODList)
			{
				// LOD tiles should be in the same directory or in nested directory
				// Basically tile path should be a prefix of a LOD tile path
				if (TileLOD.PackageName.StartsWith(TilePath))
				{
					Tile.LODPackageNames[TileLOD.LODIndex-1] = FName(*FString::Printf(TEXT("%s_LOD%d"), *TileLOD.PackageName, TileLOD.LODIndex));
				}
			}

			// Remove null entries in LOD list
			int32 NullEntryIdx;
			if (Tile.LODPackageNames.Find(FName(), NullEntryIdx))
			{
				Tile.LODPackageNames.SetNum(NullEntryIdx);
			}
		}
		
		Tiles.Add(Tile);
	}

#if WITH_EDITOR
	RestoreDirtyTilesInfo(SavedTileList);
#endif// WITH_EDITOR
	
	// Create streaming levels for each Tile
	PopulateStreamingLevels();

	// Calculate absolute positions since they are not serialized to disk
	CaclulateTilesAbsolutePositions();
}
Beispiel #6
0
void ULevelStreaming::AsyncLevelLoadComplete(const FName& InPackageName, UPackage* InLoadedPackage, EAsyncLoadingResult::Type Result)
{
	bHasLoadRequestPending = false;

	if( InLoadedPackage )
	{
		UPackage* LevelPackage = InLoadedPackage;
		
		// Try to find a UWorld object in the level package.
		UWorld* World = UWorld::FindWorldInPackage(LevelPackage);

		if ( World )
		{
			ULevel* Level = World->PersistentLevel;
			if( Level )
			{
				check(PendingUnloadLevel == NULL);
				SetLoadedLevel(Level);

				// Broadcast level loaded event to blueprints
				OnLevelLoaded.Broadcast(this);

				// Make sure this level will start to render only when it will be fully added to the world
				if (LODPackageNames.Num() > 0)
				{
					Level->bRequireFullVisibilityToRender = true;
					// LOD levels should not be visible on server
					Level->bClientOnlyVisible = LODPackageNames.Contains(InLoadedPackage->GetFName());
				}
			
				// In the editor levels must be in the levels array regardless of whether they are visible or not
				if (ensure(Level->OwningWorld) && Level->OwningWorld->WorldType == EWorldType::Editor)
				{
					Level->OwningWorld->AddLevel(Level);
#if WITH_EDITOR
					// We should also at this point, apply the level's editor transform
					if (!Level->bAlreadyMovedActors)
					{
						FLevelUtils::ApplyEditorTransform(this, false);
						Level->bAlreadyMovedActors = true;
					}
#endif // WITH_EDITOR
				}
			}
			else
			{
				UE_LOG(LogLevelStreaming, Warning, TEXT("Couldn't find ULevel object in package '%s'"), *InPackageName.ToString() );
			}
		}
		else
		{
			// There could have been a redirector in the package. Attempt to follow it.
			UObjectRedirector* WorldRedirector = nullptr;
			UWorld* DestinationWorld = UWorld::FollowWorldRedirectorInPackage(LevelPackage, &WorldRedirector);
			if (DestinationWorld)
			{
				// To follow the world redirector for level streaming...
				// 1) Update all globals that refer to the redirector package by name
				// 2) Update the PackageNameToLoad to refer to the new package location
				// 3) If the package name to load was the same as the destination package name...
				//         ... update the package name to the new package and let the next RequestLevel try this process again.
				//    If the package name to load was different...
				//         ... it means the specified package name was explicit and we will just load from another file.

				FName OldDesiredPackageName = InPackageName;
				TWeakObjectPtr<UWorld>* OwningWorldPtr = ULevel::StreamedLevelsOwningWorld.Find(OldDesiredPackageName);
				UWorld* OwningWorld = OwningWorldPtr ? OwningWorldPtr->Get() : NULL;
				ULevel::StreamedLevelsOwningWorld.Remove(OldDesiredPackageName);

				// Try again with the destination package to load.
				// IMPORTANT: check this BEFORE changing PackageNameToLoad, otherwise you wont know if the package name was supposed to be different.
				const bool bLoadingIntoDifferentPackage = (GetWorldAssetPackageFName() != PackageNameToLoad) && (PackageNameToLoad != NAME_None);

				// ... now set PackageNameToLoad
				PackageNameToLoad = DestinationWorld->GetOutermost()->GetFName();

				if ( PackageNameToLoad != OldDesiredPackageName )
				{
					EWorldType::Type* OldPackageWorldType = UWorld::WorldTypePreLoadMap.Find(OldDesiredPackageName);
					if ( OldPackageWorldType )
					{
						UWorld::WorldTypePreLoadMap.FindOrAdd(PackageNameToLoad) = *OldPackageWorldType;
						UWorld::WorldTypePreLoadMap.Remove(OldDesiredPackageName);
					}
				}

				// Now determine if we are loading into the package explicitly or if it is okay to just load the other package.
				if ( bLoadingIntoDifferentPackage )
				{
					// Loading into a new custom package explicitly. Load the destination world directly into the package.
					// Detach the linker to load from a new file into the same package.
					FLinkerLoad* PackageLinker = FLinkerLoad::FindExistingLinkerForPackage(LevelPackage);
					if (PackageLinker)
					{
						PackageLinker->Detach();
						DeleteLoader(PackageLinker);
						PackageLinker = nullptr;
					}

					// Make sure the redirector is not in the way of the new world.
					// Pass NULL as the name to make a new unique name and GetTransientPackage() for the outer to remove it from the package.
					WorldRedirector->Rename(NULL, GetTransientPackage(), REN_DoNotDirty | REN_DontCreateRedirectors | REN_ForceNoResetLoaders | REN_NonTransactional);

					// Change the loaded world's type back to inactive since it won't be used.
					DestinationWorld->WorldType = EWorldType::Inactive;
				}
				else
				{
					// Loading the requested package normally. Fix up the destination world then update the requested package to the destination.
					if (OwningWorld)
					{
						if (DestinationWorld->PersistentLevel)
						{
							DestinationWorld->PersistentLevel->OwningWorld = OwningWorld;
						}

						// In some cases, BSP render data is not created because the OwningWorld was not set correctly.
						// Regenerate that render data here
						DestinationWorld->PersistentLevel->InvalidateModelSurface();
						DestinationWorld->PersistentLevel->CommitModelSurfaces();
					}
					
					WorldAsset = DestinationWorld;
				}
			}
		}
	}
	else if (Result == EAsyncLoadingResult::Canceled)
	{
		// Cancel level streaming
		bHasLoadRequestPending = false;
		bShouldBeLoaded = false;
	}
	else
	{
		UE_LOG(LogLevelStreaming, Warning, TEXT("Failed to load package '%s'"), *InPackageName.ToString() );
	}

	// Clean up the world type list and owning world list now that PostLoad has occurred
	UWorld::WorldTypePreLoadMap.Remove(InPackageName);
	ULevel::StreamedLevelsOwningWorld.Remove(InPackageName);

	STAT_ADD_CUSTOMMESSAGE_NAME( STAT_NamedMarker, *(FString( TEXT( "RequestLevelComplete - " ) + InPackageName.ToString() )) );
}
Beispiel #7
0
bool ULevelStreaming::RequestLevel(UWorld* PersistentWorld, bool bAllowLevelLoadRequests, bool bBlockOnLoad)
{
	// Quit early in case load request already issued
	if (bHasLoadRequestPending)
	{
		return true;
	}

	// Previous attempts have failed, no reason to try again
	if (bFailedToLoad)
	{
		return false;
	}
	
	QUICK_SCOPE_CYCLE_COUNTER(STAT_ULevelStreaming_RequestLevel);
	FScopeCycleCounterUObject Context(PersistentWorld);
	// Package name we want to load
	FName DesiredPackageName = PersistentWorld->IsGameWorld() ? GetLODPackageName() : GetWorldAssetPackageFName();
	FName DesiredPackageNameToLoad = PersistentWorld->IsGameWorld() ? GetLODPackageNameToLoad() : PackageNameToLoad;

	// Check if currently loaded level is what we want right now
	if (LoadedLevel != NULL && 
		LoadedLevel->GetOutermost()->GetFName() == DesiredPackageName)
	{
		return true;
	}

	// Can not load new level now, there is still level pending unload
	if (PendingUnloadLevel != NULL)
	{
		return false;
	}
		
	// Try to find the [to be] loaded package.
	UPackage* LevelPackage = (UPackage*) StaticFindObjectFast(UPackage::StaticClass(), NULL, DesiredPackageName, 0, 0, RF_PendingKill);

	// Package is already or still loaded.
	if (LevelPackage)
	{
		// Find world object and use its PersistentLevel pointer.
		UWorld* World = UWorld::FindWorldInPackage(LevelPackage);

		// Check for a redirector. Follow it, if found.
		if ( !World )
		{
			World = UWorld::FollowWorldRedirectorInPackage(LevelPackage);
			if ( World )
			{
				LevelPackage = World->GetOutermost();
			}
		}

		if (World != NULL)
		{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
			if (World->PersistentLevel == NULL)
			{
				UE_LOG(LogLevelStreaming, Log, TEXT("World exists but PersistentLevel doesn't for %s, most likely caused by reference to world of unloaded level and GC setting reference to NULL while keeping world object"), *World->GetOutermost()->GetName());
				// print out some debug information...
				StaticExec(World, *FString::Printf(TEXT("OBJ REFS CLASS=WORLD NAME=%s shortest"), *World->GetPathName()));
				TMap<UObject*,UProperty*> Route = FArchiveTraceRoute::FindShortestRootPath( World, true, GARBAGE_COLLECTION_KEEPFLAGS );
				FString ErrorString = FArchiveTraceRoute::PrintRootPath( Route, World );
				UE_LOG(LogLevelStreaming, Log, TEXT("%s"), *ErrorString);
				// before asserting
				checkf(World->PersistentLevel,TEXT("Most likely caused by reference to world of unloaded level and GC setting reference to NULL while keeping world object"));
				return false;
			}
#endif
			if (World->PersistentLevel != LoadedLevel)
			{
				SetLoadedLevel(World->PersistentLevel);
				// Broadcast level loaded event to blueprints
				OnLevelLoaded.Broadcast(this);
			}
			
			return true;
		}
	}

	EPackageFlags PackageFlags = PKG_None;
	int32 PIEInstanceID = INDEX_NONE;

	// copy streaming level on demand if we are in PIE
	// (the world is already loaded for the editor, just find it and copy it)
	if ( PersistentWorld->IsPlayInEditor() )
	{
#if WITH_EDITOR
		if (PersistentWorld->GetOutermost()->HasAnyPackageFlags(PKG_PlayInEditor))
		{
			PackageFlags |= PKG_PlayInEditor;
		}
		PIEInstanceID = PersistentWorld->GetOutermost()->PIEInstanceID;
#endif
		const FString NonPrefixedLevelName = UWorld::StripPIEPrefixFromPackageName(DesiredPackageName.ToString(), PersistentWorld->StreamingLevelsPrefix);
		UPackage* EditorLevelPackage = FindObjectFast<UPackage>(nullptr, FName(*NonPrefixedLevelName));
		
		bool bShouldDuplicate = EditorLevelPackage && (bBlockOnLoad || EditorLevelPackage->IsDirty() || !GEngine->PreferToStreamLevelsInPIE());
		if (bShouldDuplicate)
		{
			// Do the duplication
			UWorld* PIELevelWorld = UWorld::DuplicateWorldForPIE(NonPrefixedLevelName, PersistentWorld);
			if (PIELevelWorld)
			{
				PIELevelWorld->PersistentLevel->bAlreadyMovedActors = true; // As we have duplicated the world, the actors will already have been transformed
				check(PendingUnloadLevel == NULL);
				SetLoadedLevel(PIELevelWorld->PersistentLevel);

				// Broadcast level loaded event to blueprints
				{
					QUICK_SCOPE_CYCLE_COUNTER(STAT_OnLevelLoaded_Broadcast);
					OnLevelLoaded.Broadcast(this);
				}

				return true;
			}
			else if (PersistentWorld->WorldComposition == NULL) // In world composition streaming levels are not loaded by default
			{
				if ( bAllowLevelLoadRequests )
				{
					UE_LOG(LogLevelStreaming, Log, TEXT("World to duplicate for PIE '%s' not found. Attempting load."), *NonPrefixedLevelName);
				}
				else
				{
					UE_LOG(LogLevelStreaming, Warning, TEXT("Unable to duplicate PIE World: '%s'"), *NonPrefixedLevelName);
				}
			}
		}
	}

	// Async load package if world object couldn't be found and we are allowed to request a load.
	if (bAllowLevelLoadRequests)
	{
		FString PackageNameToLoadFrom = DesiredPackageName.ToString();
		if (DesiredPackageNameToLoad != NAME_None)
		{
			PackageNameToLoadFrom = DesiredPackageNameToLoad.ToString();
		}

		if (GUseSeekFreeLoading)
		{
			// Only load localized package if it exists as async package loading doesn't handle errors gracefully.
			FString LocalizedPackageName = PackageNameToLoadFrom + LOCALIZED_SEEKFREE_SUFFIX;
			FString LocalizedFileName;
			if (FPackageName::DoesPackageExist(LocalizedPackageName, NULL, &LocalizedFileName))
			{
				// Load localized part of level first in case it exists. We don't need to worry about GC or completion 
				// callback as we always kick off another async IO for the level below.
				LoadPackageAsync(*(GetWorldAssetPackageName() + LOCALIZED_SEEKFREE_SUFFIX), nullptr, *LocalizedPackageName, FLoadPackageAsyncDelegate(), PackageFlags, PIEInstanceID);
			}
		}

		if (FPackageName::DoesPackageExist(PackageNameToLoadFrom, NULL, NULL))
		{
			bHasLoadRequestPending = true;
			
			ULevel::StreamedLevelsOwningWorld.Add(DesiredPackageName, PersistentWorld);
			UWorld::WorldTypePreLoadMap.FindOrAdd(DesiredPackageName) = PersistentWorld->WorldType;

			// Kick off async load request.
			STAT_ADD_CUSTOMMESSAGE_NAME( STAT_NamedMarker, *(FString( TEXT( "RequestLevel - " ) + DesiredPackageName.ToString() )) );
			LoadPackageAsync(DesiredPackageName.ToString(), nullptr, *PackageNameToLoadFrom, FLoadPackageAsyncDelegate::CreateUObject(this, &ULevelStreaming::AsyncLevelLoadComplete), PackageFlags, PIEInstanceID);

			// streamingServer: server loads everything?
			// Editor immediately blocks on load and we also block if background level streaming is disabled.
			if (bBlockOnLoad || ShouldBeAlwaysLoaded())
			{
				// Finish all async loading.
				FlushAsyncLoading();
			}
		}
		else
		{
			UE_LOG(LogStreaming, Error,TEXT("Couldn't find file for package %s."), *PackageNameToLoadFrom);
			bFailedToLoad = true;
			return false;
		}
	}

	return true;
}
void AOnlineBeaconHost::NotifyControlMessage(UNetConnection* Connection, uint8 MessageType, class FInBunch& Bunch)
{
	if(NetDriver->ServerConnection == nullptr)
	{
		bool bCloseConnection = false;

		// We are the server.
#if !(UE_BUILD_SHIPPING && WITH_EDITOR)
		UE_LOG(LogBeacon, Verbose, TEXT("%s[%s] Host received: %s"), *GetName(), Connection ? *Connection->GetName() : TEXT("Invalid"), FNetControlMessageInfo::GetName(MessageType));
#endif
		switch (MessageType)
		{
		case NMT_Hello:
			{
				UE_LOG(LogBeacon, Log, TEXT("Beacon Hello"));
				uint8 IsLittleEndian;

				uint32 RemoteNetworkVersion = 0;
				uint32 LocalNetworkVersion = FNetworkVersion::GetLocalNetworkVersion();

				FNetControlMessage<NMT_Hello>::Receive(Bunch, IsLittleEndian, RemoteNetworkVersion);

				if (!FNetworkVersion::IsNetworkCompatible(LocalNetworkVersion, RemoteNetworkVersion))
				{
					UE_LOG(LogBeacon, Log, TEXT("Client not network compatible %s"), *Connection->GetName());
					FNetControlMessage<NMT_Upgrade>::Send(Connection, LocalNetworkVersion);
					bCloseConnection = true;
				}
				else
				{
					Connection->Challenge = FString::Printf(TEXT("%08X"), FPlatformTime::Cycles());
					FNetControlMessage<NMT_BeaconWelcome>::Send(Connection);
					Connection->FlushNet();
				}
				break;
			}
		case NMT_Netspeed:
			{
				int32 Rate;
				FNetControlMessage<NMT_Netspeed>::Receive(Bunch, Rate);
				Connection->CurrentNetSpeed = FMath::Clamp(Rate, 1800, NetDriver->MaxClientRate);
				UE_LOG(LogBeacon, Log, TEXT("Client netspeed is %i"), Connection->CurrentNetSpeed);
				break;
			}
		case NMT_BeaconJoin:
			{
				FString ErrorMsg;
				FString BeaconType;
				FUniqueNetIdRepl UniqueId;
				FNetControlMessage<NMT_BeaconJoin>::Receive(Bunch, BeaconType, UniqueId);
				UE_LOG(LogBeacon, Log, TEXT("Beacon Join %s %s"), *BeaconType, *UniqueId.ToDebugString());

				if (Connection->ClientWorldPackageName == NAME_None)
				{
					AOnlineBeaconClient* ClientActor = GetClientActor(Connection);
					if (ClientActor == nullptr)
					{
						UWorld* World = GetWorld();
						Connection->ClientWorldPackageName = World->GetOutermost()->GetFName();

						AOnlineBeaconClient* NewClientActor = nullptr;
						FOnBeaconSpawned* OnBeaconSpawnedDelegate = OnBeaconSpawnedMapping.Find(BeaconType);
						if (OnBeaconSpawnedDelegate && OnBeaconSpawnedDelegate->IsBound())
						{
							NewClientActor = OnBeaconSpawnedDelegate->Execute(Connection);
						}

						if (NewClientActor && BeaconType == NewClientActor->GetBeaconType())
						{
							NewClientActor->SetConnectionState(EBeaconConnectionState::Pending);

							FNetworkGUID NetGUID = Connection->Driver->GuidCache->AssignNewNetGUID_Server(NewClientActor);
							NewClientActor->SetNetConnection(Connection);
							Connection->PlayerId = UniqueId;
							Connection->OwningActor = NewClientActor;
							NewClientActor->Role = ROLE_Authority;
							NewClientActor->SetReplicates(false);
							check(NetDriverName == NetDriver->NetDriverName);
							NewClientActor->SetNetDriverName(NetDriverName);
							ClientActors.Add(NewClientActor);
							FNetControlMessage<NMT_BeaconAssignGUID>::Send(Connection, NetGUID);
						}
						else
						{
							ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnFailureError", "Join failure, Couldn't spawn beacon.").ToString();
						}
					}
					else
					{
						ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnExistingActorError", "Join failure, existing beacon actor.").ToString();
					}
				}
				else
				{
					ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnClientWorldPackageNameError", "Join failure, existing ClientWorldPackageName.").ToString();
				}

				if (!ErrorMsg.IsEmpty())
				{
					UE_LOG(LogBeacon, Log, TEXT("%s: %s"), *Connection->GetName(), *ErrorMsg);
					FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg);
					bCloseConnection = true;
				}

				break;
			}
		case NMT_BeaconNetGUIDAck:
			{
				FString ErrorMsg;
				FString BeaconType;
				FNetControlMessage<NMT_BeaconNetGUIDAck>::Receive(Bunch, BeaconType);

				AOnlineBeaconClient* ClientActor = GetClientActor(Connection);
				if (ClientActor && BeaconType == ClientActor->GetBeaconType())
				{
					FOnBeaconConnected* OnBeaconConnectedDelegate = OnBeaconConnectedMapping.Find(BeaconType);
					if (OnBeaconConnectedDelegate)
					{
						ClientActor->SetReplicates(true);
						ClientActor->SetAutonomousProxy(true);
						ClientActor->SetConnectionState(EBeaconConnectionState::Open);
						// Send an RPC to the client to open the actor channel and guarantee RPCs will work
						ClientActor->ClientOnConnected();
						UE_LOG(LogBeacon, Log, TEXT("Handshake complete for %s!"), *ClientActor->GetName());

						OnBeaconConnectedDelegate->ExecuteIfBound(ClientActor, Connection);
					}
					else
					{
						// Failed to connect.
						ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnNetGUIDAckError1", "Join failure, no host object at NetGUIDAck.").ToString();
					}
				}
				else
				{
					// Failed to connect.
					ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnNetGUIDAckError2", "Join failure, no actor at NetGUIDAck.").ToString();
				}

				if (!ErrorMsg.IsEmpty())
				{
					UE_LOG(LogBeacon, Log, TEXT("%s: %s"), *Connection->GetName(), *ErrorMsg);
					FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg);
					bCloseConnection = true;
				}

				break;
			}
		case NMT_BeaconWelcome:
		case NMT_BeaconAssignGUID:
		default:
			{
				FString ErrorMsg = NSLOCTEXT("NetworkErrors", "BeaconSpawnUnexpectedError", "Join failure, unexpected control message.").ToString();
				UE_LOG(LogBeacon, Log, TEXT("%s: %s"), *Connection->GetName(), *ErrorMsg);
				FNetControlMessage<NMT_Failure>::Send(Connection, ErrorMsg);
				bCloseConnection = true;
			}
			break;
		}

		if (bCloseConnection)
		{		
			UE_LOG(LogBeacon, Verbose, TEXT("Closing connection %s: %s"), *Connection->GetName(), *Connection->PlayerId.ToDebugString());
			AOnlineBeaconClient* ClientActor = GetClientActor(Connection);
			if (ClientActor)
			{
				UE_LOG(LogBeacon, Verbose, TEXT("- BeaconActor: %s %s"), *ClientActor->GetName(), *ClientActor->GetBeaconType());
				AOnlineBeaconHostObject* BeaconHostObject = GetHost(ClientActor->GetBeaconType());
				if (BeaconHostObject)
				{
					UE_LOG(LogBeacon, Verbose, TEXT("- HostObject: %s"), *BeaconHostObject->GetName());
					BeaconHostObject->NotifyClientDisconnected(ClientActor);
				}

				RemoveClientActor(ClientActor);
			}

			Connection->FlushNet(true);
			Connection->Close();
			UE_LOG(LogBeacon, Verbose, TEXT("--------------------------------"));
		}
	}
}