132 lines
3.5 KiB
C++
132 lines
3.5 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "PocketLevelInstance.h"
|
|
#include "PocketLevel.h"
|
|
#include "Engine/LevelStreamingDynamic.h"
|
|
#include "Engine/Level.h"
|
|
#include "Engine/LocalPlayer.h"
|
|
#include "GameFramework/Actor.h"
|
|
#include "GameFramework/PlayerController.h"
|
|
|
|
UPocketLevelInstance::UPocketLevelInstance()
|
|
{
|
|
|
|
}
|
|
|
|
bool UPocketLevelInstance::Initialize(ULocalPlayer* InLocalPlayer, UPocketLevel* InPocketLevel, FVector InSpawnPoint)
|
|
{
|
|
LocalPlayer = InLocalPlayer;
|
|
World = LocalPlayer->GetWorld();
|
|
PocketLevel = InPocketLevel;
|
|
Bounds = FBoxSphereBounds(FSphere(InSpawnPoint, PocketLevel->Bounds.GetAbsMax()));
|
|
|
|
if (ensure(StreamingPocketLevel == nullptr))
|
|
{
|
|
if (ensure(!PocketLevel->Level.IsNull()))
|
|
{
|
|
bool bSuccess = false;
|
|
StreamingPocketLevel = ULevelStreamingDynamic::LoadLevelInstanceBySoftObjectPtr(LocalPlayer, PocketLevel->Level, Bounds.Origin, FRotator::ZeroRotator, bSuccess);
|
|
|
|
if (ensure(bSuccess && StreamingPocketLevel))
|
|
{
|
|
StreamingPocketLevel->OnLevelLoaded.AddUniqueDynamic(this, &ThisClass::HandlePocketLevelLoaded);
|
|
StreamingPocketLevel->OnLevelShown.AddUniqueDynamic(this, &ThisClass::HandlePocketLevelShown);
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void UPocketLevelInstance::StreamIn()
|
|
{
|
|
if (StreamingPocketLevel)
|
|
{
|
|
StreamingPocketLevel->SetShouldBeVisible(true);
|
|
StreamingPocketLevel->SetShouldBeLoaded(true);
|
|
}
|
|
}
|
|
|
|
void UPocketLevelInstance::StreamOut()
|
|
{
|
|
if (StreamingPocketLevel)
|
|
{
|
|
StreamingPocketLevel->SetShouldBeVisible(false);
|
|
StreamingPocketLevel->SetShouldBeLoaded(false);
|
|
}
|
|
}
|
|
|
|
FDelegateHandle UPocketLevelInstance::AddReadyCallback(FPocketLevelInstanceEvent::FDelegate Callback)
|
|
{
|
|
if (StreamingPocketLevel->GetCurrentState() == ULevelStreaming::ECurrentState::LoadedVisible)
|
|
{
|
|
Callback.ExecuteIfBound(this);
|
|
}
|
|
|
|
return OnReadyEvent.Add(Callback);
|
|
}
|
|
|
|
void UPocketLevelInstance::RemoveReadyCallback(FDelegateHandle CallbackToRemove)
|
|
{
|
|
OnReadyEvent.Remove(CallbackToRemove);
|
|
}
|
|
|
|
void UPocketLevelInstance::BeginDestroy()
|
|
{
|
|
Super::BeginDestroy();
|
|
|
|
if (StreamingPocketLevel)
|
|
{
|
|
StreamingPocketLevel->bShouldBlockOnUnload = false;
|
|
StreamingPocketLevel->SetShouldBeLoaded(false);
|
|
StreamingPocketLevel->OnLevelShown.RemoveAll(this);
|
|
StreamingPocketLevel->OnLevelLoaded.RemoveAll(this);
|
|
StreamingPocketLevel = nullptr;
|
|
}
|
|
}
|
|
|
|
void UPocketLevelInstance::HandlePocketLevelLoaded()
|
|
{
|
|
if (StreamingPocketLevel)
|
|
{
|
|
// Make everything in the level setup so that it's setup on the client, and we treat
|
|
// everything as locally spawned, rather than bExchangedRoles = true, where it's spawned
|
|
// on the client, but the expectation is the server said do it, and the server is going to
|
|
// be telling us about them later.
|
|
if (ULevel* LoadedLevel = StreamingPocketLevel->GetLoadedLevel())
|
|
{
|
|
LoadedLevel->bClientOnlyVisible = true;
|
|
|
|
for (AActor* Actor : LoadedLevel->Actors)
|
|
{
|
|
if (Actor)
|
|
{
|
|
Actor->bExchangedRoles = true; // HACK, Remove when bClientOnlyVisible is all we need.
|
|
}
|
|
}
|
|
|
|
// TODO: Don't put ownership over shared pocket spaces.
|
|
if (LocalPlayer)
|
|
{
|
|
if (APlayerController* PC = LocalPlayer->GetPlayerController(GetWorld()))
|
|
{
|
|
for (AActor* Actor : LoadedLevel->Actors)
|
|
{
|
|
if (Actor)
|
|
{
|
|
Actor->SetOwner(PC);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UPocketLevelInstance::HandlePocketLevelShown()
|
|
{
|
|
OnReadyEvent.Broadcast(this);
|
|
}
|