I managed to get ahead a little. I was able to move between the created world and then back. The problem is that in the Standalone game, recreating UWorld causes the editor to crash. I don’t know what could be the problem, can anyone help me?
.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "GameBFL.generated.h"
USTRUCT(BlueprintType)
struct FUWorldContext
{
GENERATED_BODY()
public:
//~ The following member variable will be accessible by Blueprint Graphs:
// This is the tooltip for our test variable.
//~ The following member variable will be not accessible by Blueprint Graphs:
int32 NativeOnlyMemberVariable;
/**~
* This UObject pointer is not accessible to Blueprint Graphs, but
* is visible to UE4's reflection, smart pointer, and garbage collection
* systems.
*/
UPROPERTY()
UObject* SafeObjectPointer;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Test Variables")
UWorld* ContextWorld;
private:
//FWorldContext* WorldContext;
public:
void SetWorldContext(FWorldContext* inContext) { ContextWorld = inContext->World(); }
};
/**
*
*/
UCLASS()
class GAMEPROJECT_API UGameBFL : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable)
static TArray<uint8> SaveToBinaryArray(UObject* Object, bool IsSaveGameOnly);
UFUNCTION(BlueprintCallable)
static void LoadFromBinaryArray(TArray<uint8> SaveData, UObject* Object, bool IsSaveGameOnly);
UFUNCTION(BlueprintCallable)
static void CreateNavigationData(UObject* World);
UFUNCTION(BlueprintCallable)
static void BuildNavigation(UObject* World);
UFUNCTION(BlueprintCallable)
static TArray<uint8> SaveNavData(UObject* World);
UFUNCTION(BlueprintCallable)
static void LoadNavData(UObject* World, TArray<uint8> data);
//UWorlds ==============================================================================================================
UFUNCTION(BlueprintCallable, meta = (WorldContextObject = "WorldContextObject"))
static void CreateNewWorld_OLD(const UObject* WorldContextObject, FString LevelName, const TSoftObjectPtr<UWorld> Level, UWorld*& World);
static UWorld* CreateWorld(const EWorldType::Type InWorldType, bool bInformEngineOfWorld, FName WorldName = NAME_None, UPackage* InWorldPackage = NULL, bool bAddToRoot = true, ERHIFeatureLevel::Type InFeatureLevel = ERHIFeatureLevel::Num);
UFUNCTION(BlueprintCallable, meta = (WorldContextObject = "WorldContextObject"))
static void CreateNewWorld2_OLD(const UObject* WorldContextObject, const TSoftObjectPtr<UWorld> Level, FUWorldContext& UWorldContext);
UFUNCTION(BlueprintCallable)
static void CreateNewWorld3(const TSoftObjectPtr<UWorld> Level, const TSubclassOf<class AGameModeBase> GameMode, FUWorldContext& UWorldContext);
UFUNCTION(BlueprintCallable, meta = (WorldContextObject = "WorldContextObject"))
static void DestroyCreatedWorld(FUWorldContext UWorldContext);
static TMap<UWorld*,FDelegateHandle> CleanupHandles;
static FDelegateHandle CleanupHandle;
static TMap<UWorld*, FDelegateHandle> TickHandles;
static FDelegateHandle TickHandle;
static TArray<UWorld*> CreatedWorlds;
UFUNCTION(BlueprintCallable)
static void WorldBeginPlay(UObject* World);
UFUNCTION(BlueprintPure)
static UWorld* GetMainWorld();
UFUNCTION(BlueprintPure)
static FUWorldContext GetMainWorldContext();
//UWorlds end ==========================================================================================================
//UWorlds switch world side ===========================================================================================
UFUNCTION(BlueprintCallable)
static APlayerController* FindPCInWorlds();
UFUNCTION(BlueprintCallable)
static APlayerController* ChangeWorld(FUWorldContext UWorldContext, APawn*& PrevPawn);
/*UFUNCTION(BlueprintCallable)
static APlayerController* FindPCInWorlds(UObject* World);*/
//UWorlds switch world side end =======================================================================================
UFUNCTION(BlueprintCallable)
static void ProcessTick(TArray<UObject*> Objects, float DeltaSeconds);
UFUNCTION(BlueprintCallable, meta = (DeterminesOutputType = "InputActor"))
static AActor* CloneActor(const UObject* WorldContextObject, AActor* InputActor, FTransform Transform);
UFUNCTION(BlueprintCallable)
static void RerunConstructionScripts(AActor* Actor);
//UFUNCTION(BlueprintCallable)
// AActor* SpawnActorForLoad(const UObject* WorldContextObject, UClass* Class, FTransform const* Transform, AActor* Owner, APawn* Instigator);
/**
* Renders a widget to a Render Texture 2D with the given draw size.
*
* @param widget The widget to converted to a Render Texture 2D.
* @param drawSize The size to render the Widget to. Also will be the texture size.
* @return The texture render target 2D containing the rendered widget.
*/
UFUNCTION(BlueprintCallable)
static UTextureRenderTarget2D* WidgetToTexture(UUserWidget* const widget, const FVector2D& drawSize);
/**
*Renders a UMG Widget to a texture with the specified size.
*
* @param Widget The widget to be rendered.
* @param DrawSize The size to render the Widget to.Also will be the texture size.
* @return The texture containing the rendered widget.
*/
UFUNCTION(BlueprintCallable)
static UTexture2D* TextureFromWidget(UUserWidget* const Widget, const FVector2D& DrawSize);
UFUNCTION(BlueprintCallable)
static void PressAnyKey(FKey Key);
UFUNCTION(BlueprintCallable)
static void ReleaseAnyKey(FKey Key);
UFUNCTION(BlueprintCallable)
static void GetDerivedClassesOfClass(const UClass* ClassToLookFor, TArray< UClass* >& Results, bool bRecursive);
};
.cpp
#include "GameBFL.h"
#include "Serialization/ObjectAndNameAsStringProxyArchive.h"
#include "EngineUtils.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/GameModeBase.h"
#include "NavigationSystem.h"
#include "NavMesh/RecastNavMesh.h"
#include "UObject/UObjectHash.h"
#include "GameFramework/PlayerController.h"
TMap<UWorld*, FDelegateHandle> UGameBFL::CleanupHandles;
FDelegateHandle UGameBFL::CleanupHandle;
TMap<UWorld*, FDelegateHandle> UGameBFL::TickHandles;
FDelegateHandle UGameBFL::TickHandle;
TArray<UWorld*> UGameBFL::CreatedWorlds;
FUWorldContext UGameBFL::GetMainWorldContext()
{
FUWorldContext UWorldContext;
UWorldContext.ContextWorld = GEngine->GetCurrentPlayWorld();
return UWorldContext;
}
UWorld* UGameBFL::GetMainWorld()
{
return GEngine->GetCurrentPlayWorld();
}
APlayerController* UGameBFL::FindPCInWorlds()
{
//GEngine->GameViewport->Viewport;
//GetGameViewport()->bDisableWorldRendering;
//WorldContext->GameViewport;
//auto OldWorld = Cast<UWorld>(World);
//return OldWorld->GetFirstPlayerController();
APlayerController* PC = nullptr;
PC = GetMainWorld()->GetFirstPlayerController();
if (!PC) {
for (auto CurWorld : CreatedWorlds)
{
PC = CurWorld->GetFirstPlayerController();
if (PC) break;
}
}
return PC ? PC : nullptr;
}
APlayerController* UGameBFL::ChangeWorld(FUWorldContext UWorldContext, APawn*& PrevPawn) {
//auto NewWorld = ToWorld;
auto NewWorld = UWorldContext.ContextWorld;
//if (ToWorld) NewWorld = ToWorld;
if (!IsValid(NewWorld)) return nullptr;
auto WorldContext = GEngine->GetWorldContextFromWorld(NewWorld);
auto GameInstance = UGameplayStatics::GetGameInstance(GetMainWorld());
//auto context = GameInstance->GetWorldContext()->GameViewport;
//switch render to new UWorld
NewWorld->GetGameViewport()->Init(*WorldContext, GameInstance);
//find PC in worlds
APlayerController* PC = nullptr;
PC = GetMainWorld()->GetFirstPlayerController();
if (!PC) {
for (auto CurWorld : CreatedWorlds)
{
PC = CurWorld->GetFirstPlayerController();
if (PC) break;
}
}
if (PC) PrevPawn = PC->GetPawn();
return PC ? PC : nullptr;
}
//void UGameBFL::CreateNewWorld3(const UObject* WorldContextObject, const TSoftObjectPtr<UWorld> Level, UWorld*& World, FUWorldContext& UWorldContext)
void UGameBFL::CreateNewWorld3(const TSoftObjectPtr<UWorld> Level, TSubclassOf<class AGameModeBase> GameMode, FUWorldContext& UWorldContext)
{
UWorld* NewWorld = nullptr;
const FString LevelName2 = FPackageName::ObjectPathToPackageName(Level.ToString());
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("level name = %s"), *LevelName2));
UPackage* WorldPackage = FindPackage(nullptr, *LevelName2);
if (WorldPackage == nullptr)
{
WorldPackage = LoadPackage(nullptr, *LevelName2, ELoadFlags::LOAD_None);
if (!WorldPackage)
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Package not loaded")));
return;
}
}
///======
if (!WorldPackage)
{
WorldPackage = CreatePackage(nullptr);
}
//if (InWorldType == EWorldType::PIE)
//{
// WorldPackage->SetPackageFlags(PKG_PlayInEditor);
//}
// Mark the package as containing a world. This has to happen here rather than at serialization time,
// so that e.g. the referenced assets browser will work correctly.
if (WorldPackage != GetTransientPackage())
{
WorldPackage->ThisContainsMap();
}
///======
UPackage* NewWorldPackage = CreatePackage(nullptr);
NewWorldPackage->SetPackageFlags(PKG_PlayInEditor);
NewWorldPackage->PIEInstanceID = WorldPackage->GetPIEInstanceID();
NewWorldPackage->FileName = FName(*WorldPackage->GetName());
NewWorldPackage->SetGuid(WorldPackage->GetGuid());
NewWorldPackage->MarkAsFullyLoaded();
UWorld* PackageWorld = UWorld::FindWorldInPackage(WorldPackage);
FObjectDuplicationParameters Parameters(PackageWorld, NewWorldPackage);
//Parameters.DestName = PackageWorld->GetFName();
Parameters.DestName = FName();
Parameters.DestClass = PackageWorld->GetClass();
Parameters.DuplicateMode = EDuplicateMode::PIE;
Parameters.PortFlags = EPropertyPortFlags::PPF_Duplicate;
NewWorld = CastChecked<UWorld>(StaticDuplicateObjectEx(Parameters));
//NewWorld = UWorld::DuplicateWorldForPIE(LevelName2, PackageWorld);
//if (!NewWorld)
//{
// return;
//}
//const FString WorldNameString = "CreatedMap" + FString::FromInt(FMath::RandRange(0, 100));
//NewWorld = UWorld::CreateWorld(EWorldType::PIE, true, FName(*WorldNameString));
//NewWorld = UWorld::CreateWorld(EWorldType::Game, true, FName("CreatedMap"), WorldPackage);
NewWorld->SetShouldTick(true);
FWorldContext& WorldContext = GEngine->CreateNewWorldContext(EWorldType::Game);
//WorldContext.OwningGameInstance = UGameplayStatics::GetGameInstance(WorldContextObject);
WorldContext.OwningGameInstance = UGameplayStatics::GetGameInstance(GEngine->GetCurrentPlayWorld());
//WorldContext.PIEInstance = -1;
NewWorld->SetGameInstance(UGameplayStatics::GetGameInstance(GEngine->GetCurrentPlayWorld()));
////NewWorld->WorldType = WorldContext.WorldType;
NewWorld->WorldType = EWorldType::PIE;
WorldContext.SetCurrentWorld(NewWorld);
auto GameInstance = UGameplayStatics::GetGameInstance(GetMainWorld());
auto context = GameInstance->GetWorldContext()->GameViewport;
//ViewportClient->Init(*GameInstance->GetWorldContext(), GameInstance);
WorldContext.GameViewport = context;
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("CreateWorld: %s"), *NewWorld->GetFName().ToString()));
//// In the PIE case the world will already have been initialized as part of CreatePIEWorldByDuplication
if (!WorldContext.World()->bIsWorldInitialized)
{
WorldContext.World()->InitWorld();
}
/*FNavigationSystemRunMode ResolvedRunMode(FNavigationSystemRunMode::GameMode);
switch (NewWorld->WorldType)
{
case EWorldType::Editor:
case EWorldType::EditorPreview:
ResolvedRunMode = FNavigationSystemRunMode::EditorMode;
break;
case EWorldType::PIE:
ResolvedRunMode = FNavigationSystemRunMode::PIEMode;
break;
case EWorldType::Game:
case EWorldType::GamePreview:
case EWorldType::GameRPC:
ResolvedRunMode = FNavigationSystemRunMode::GameMode;
break;
case EWorldType::Inactive:
case EWorldType::None:
ResolvedRunMode = FNavigationSystemRunMode::InvalidMode;
break;
default:
UE_LOG(LogNavigation, Warning, TEXT("%s Unhandled world type, defaulting to FNavigationSystemRunMode::InvalidMode."), ANSI_TO_TCHAR(__FUNCTION__));
ResolvedRunMode = FNavigationSystemRunMode::InvalidMode;
}
if (NewWorld->GetNavigationSystem())
{
NewWorld->GetNavigationSystem()->InitializeForWorld(*NewWorld, ResolvedRunMode);
}*/
//else if (ResolvedRunMode == FNavigationSystemRunMode::EditorMode)
//{
// DiscardNavigationDataChunks(WorldOwner);
//}
FURL URL;
//FURL URL(&WorldContext.LastURL, *NewWorld->GetFName().ToString(), ETravelType::TRAVEL_Absolute);
FString GamemodePath = FString("GAME=") + GameMode->GetPathName();
//URL.AddOption(TEXT("GAME=/Game/Blueprints/GameModeBP_CreatedWorld.GameModeBP_CreatedWorld_C"));
const TCHAR* GMPath = *GamemodePath;
URL.AddOption(GMPath);
WorldContext.World()->SetGameMode(URL);
//WorldContext.World()->CreateAISystem();
WorldContext.World()->InitializeActorsForPlay(URL);
//AActor* lacder = nullptr;
for (auto actor : NewWorld->PersistentLevel->Actors) {
UE_LOG(LogTemp, Warning, TEXT("LoadedWorldActorsClasses: %s"), *UKismetSystemLibrary::GetDisplayName(actor));
//if (actor->GetClass()->GetName() == "BpGameMode2_C")
//{
// //lacder = actor;
//}
}
UFunction* Func = NewWorld->GetAuthGameMode()->GetClass()->FindFunctionByName(FName("Load"));
if (Func == nullptr) {
return;
}
FStructOnScope FuncParam(Func);
NewWorld->GetAuthGameMode()->ProcessEvent(Func, FuncParam.GetStructMemory());
//UNavigationSystemV1 *NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(NewWorld);
//if (NavSys)
//{
// ANavigationData *UseNavData = NavSys->GetDefaultNavDataInstance(FNavigationSystem::Create);
// NavSys->Build();
//}
WorldContext.World()->BeginPlay();
WorldContext.World()->bWorldWasLoadedThisTick = true;
//if (!CleanupHandle.IsValid()) {
// Tick call in PIE
auto TickHandle2 = FWorldDelegates::OnWorldTickStart.AddLambda([NewWorld](UWorld* World, ELevelTick TickType, float DeltaSeconds) {
if (World == GetMainWorld() && GetMainWorld()->WorldType == EWorldType::PIE) {
auto TickHand = TickHandles.Find(NewWorld);
if (TickHand->IsValid()) {
if (NewWorld->ShouldTick())
{
NewWorld->Tick(TickType, DeltaSeconds);
//GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Yellow, FString::Printf(TEXT("TickInWorld: %s"), *NewWorld->GetFName().ToString()));
//UE_LOG(LogTemp, Warning, TEXT("TickInWorld: %s"), *NewWorld->GetFName().ToString());
}
}
}});
if (TickHandle.IsValid())
{
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Yellow, FString::Printf(TEXT("TickHackSet")));
UE_LOG(LogTemp, Warning, TEXT("TickHackSet"));
}
TickHandles.Add(NewWorld, TickHandle2);
auto CHandle = FWorldDelegates::OnPostWorldCleanup.AddLambda([NewWorld](UWorld* World, bool bSessionEnded, bool bCleanupResources) {
if (!CreatedWorlds.Contains(World)) {;
auto CLHandle = CleanupHandles.Find(NewWorld);
if (CLHandle) {
FWorldDelegates::OnPostWorldCleanup.Remove(*CLHandle);
CLHandle->Reset();
CleanupHandles.Remove(NewWorld);
}
auto TickHand = TickHandles.Find(NewWorld);
if (TickHand && TickHand->IsValid()) {
FWorldDelegates::OnWorldTickStart.Remove(*TickHand);
TickHand->Reset();
TickHandles.Remove(NewWorld);
}
if (NewWorld) {
auto Name = NewWorld->GetMapName();
for (FActorIterator ActorIt(NewWorld); ActorIt; ++ActorIt)
{
//ActorIt->RouteEndPlay(EEndPlayReason::LevelTransition);
ActorIt->Destroy();
}
// Do this after destroying pawns/playercontrollers, in case that spawns new things (e.g. dropped weapons)
//WorldRef->CleanupWorld();
//GEngine->WorldDestroyed(WorldRef);
CreatedWorlds.Remove(NewWorld);
GEngine->DestroyWorldContext(NewWorld);
NewWorld->DestroyWorld(true);
GEngine->TrimMemory();
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Created World destroyed: %s"), *WorldRef->GetFName().ToString()));
UE_LOG(LogTemp, Warning, TEXT("Created World destroyed: %s"), *Name);
}
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("DestroyedWorld: %s"), *World->GetFName().ToString()));
UE_LOG(LogTemp, Warning, TEXT("DestroyedWorld: %s"), *World->GetFName().ToString());
}
});
CleanupHandles.Add(NewWorld, CHandle);
//}
CreatedWorlds.Add(NewWorld);
UWorldContext.SetWorldContext(&WorldContext);
//World = NewWorld;
//
//
//auto vp = World->GetGameViewport();
//if (vp) {
// GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Exist viewport")));
// //World->GetGameViewport()->Init(WorldContext, GameInstance);
// GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Player: %d"), World->GetAuthGameMode()->GetNumPlayers()));
//
//}
//else
//{
// GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("No viewport")));
//}
//GEngine->GameViewport->Viewport->;
//FViewportClient* Client = GEngine->GameViewport->Viewport->GetClient();
//Client->
//FViewport::SetViewportClient;
}
void UGameBFL::DestroyCreatedWorld(FUWorldContext UWorldContext) {
//auto WorldRef = Cast<UWorld>(World->GetWorld());
auto WorldRef = UWorldContext.ContextWorld;
//WorldRef->SetShouldTick(false);
if (CreatedWorlds.Contains(WorldRef)) {
/*auto CleanDelegat = CleanupHandles.Find(WorldRef);
if (CleanDelegat->IsValid()) {
FWorldDelegates::OnPostWorldCleanup.Remove(*CleanDelegat);
CleanDelegat->Reset();
}*/
auto TickHand = TickHandles.Find(WorldRef);
if (TickHand && TickHand->IsValid()) {
FWorldDelegates::OnWorldTickStart.Remove(*TickHand);
TickHand->Reset();
TickHandles.Remove(WorldRef);
}
CreatedWorlds.Remove(WorldRef);
}
if (WorldRef) {
auto WorldName = WorldRef->GetMapName();
WorldRef->DestroyWorld(true);
WorldRef->MarkAsGarbage();
UE_LOG(LogTemp, Warning, TEXT("Destroy UWorld from player event: %s"), *WorldName);
}
//if (WorldRef)
//{
//
// auto WorldName = WorldRef->GetMapName();
// for (FActorIterator ActorIt(WorldRef); ActorIt; ++ActorIt)
// {
//
// //ActorIt->RouteEndPlay(EEndPlayReason::LevelTransition);
// ActorIt->Destroy();
// }
// // Do this after destroying pawns/playercontrollers, in case that spawns new things (e.g. dropped weapons)
// //WorldRef->CleanupWorld();
//
// //GEngine->DestroyWorldContext(WorldRef);
// GEngine->WorldDestroyed(WorldRef);
// WorldRef->DestroyWorld(true);
//
// GEngine->TrimMemory();
// //GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Created World destroyed: %s"), *WorldRef->GetFName().ToString()));
// UE_LOG(LogTemp, Warning, TEXT("Destroy from player event: %s"), *WorldName);
//}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// World old //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UGameBFL::CreateNewWorld2_OLD(const UObject* WorldContextObject, const TSoftObjectPtr<UWorld> Level, FUWorldContext& UWorldContext)
{
UWorld* NewWorld = nullptr;
const FString LevelName2 = FPackageName::ObjectPathToPackageName(Level.ToString());
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("level name = %s"), *LevelName2));
UPackage* WorldPackage = FindPackage(nullptr, *LevelName2);
if (WorldPackage == nullptr)
{
WorldPackage = LoadPackage(nullptr, *LevelName2, ELoadFlags::LOAD_None);
if (!WorldPackage)
{
GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Package not loaded")));
return;
}
}
UWorld* PackageWorld = UWorld::FindWorldInPackage(WorldPackage);
UPackage* NewWorldPackage = CreatePackage(nullptr);
//NewWorldPackage->SetPackageFlags(PKG_PlayInEditor);
//NewWorldPackage->PIEInstanceID = PIEInstanceID;
//NewWorldPackage->FileName = PackageFName;
//NewWorldPackage->SetGuid(EditorLevelPackage->GetGuid());
//NewWorldPackage->MarkAsFullyLoaded();
FObjectDuplicationParameters Parameters(PackageWorld, NewWorldPackage);
Parameters.DestName = PackageWorld->GetFName();
Parameters.DestClass = PackageWorld->GetClass();
Parameters.DuplicateMode = EDuplicateMode::PIE;
Parameters.PortFlags = EPropertyPortFlags::PPF_Duplicate;
NewWorld = CastChecked<UWorld>(StaticDuplicateObjectEx(Parameters));
//NewWorld = UWorld::DuplicateWorldForPIE(LevelName2, PackageWorld);
//if (!NewWorld)
//{
// return;
//}
//const FString WorldNameString = "CreatedMap" + FString::FromInt(FMath::RandRange(0, 100));
//NewWorld = UWorld::CreateWorld(EWorldType::PIE, true, FName(*WorldNameString));
//NewWorld = UWorld::CreateWorld(EWorldType::Game, true, FName("CreatedMap"), WorldPackage);
NewWorld->SetShouldTick(true);
FWorldContext& WorldContext = GEngine->CreateNewWorldContext(EWorldType::Game);
WorldContext.OwningGameInstance = UGameplayStatics::GetGameInstance(WorldContextObject);
//WorldContext.PIEInstance = -1;
NewWorld->SetGameInstance(UGameplayStatics::GetGameInstance(WorldContextObject));
////NewWorld->WorldType = WorldContext.WorldType;
NewWorld->WorldType = EWorldType::PIE;
WorldContext.SetCurrentWorld(NewWorld);
auto GameInstance = UGameplayStatics::GetGameInstance(GetMainWorld());
auto context = GameInstance->GetWorldContext()->GameViewport;
//ViewportClient->Init(*GameInstance->GetWorldContext(), GameInstance);
WorldContext.GameViewport = context;
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("CreateWorld: %s"), *NewWorld->GetFName().ToString()));
//// In the PIE case the world will already have been initialized as part of CreatePIEWorldByDuplication
if (!WorldContext.World()->bIsWorldInitialized)
{
WorldContext.World()->InitWorld();
}
/*FNavigationSystemRunMode ResolvedRunMode(FNavigationSystemRunMode::GameMode);
switch (NewWorld->WorldType)
{
case EWorldType::Editor:
case EWorldType::EditorPreview:
ResolvedRunMode = FNavigationSystemRunMode::EditorMode;
break;
case EWorldType::PIE:
ResolvedRunMode = FNavigationSystemRunMode::PIEMode;
break;
case EWorldType::Game:
case EWorldType::GamePreview:
case EWorldType::GameRPC:
ResolvedRunMode = FNavigationSystemRunMode::GameMode;
break;
case EWorldType::Inactive:
case EWorldType::None:
ResolvedRunMode = FNavigationSystemRunMode::InvalidMode;
break;
default:
UE_LOG(LogNavigation, Warning, TEXT("%s Unhandled world type, defaulting to FNavigationSystemRunMode::InvalidMode."), ANSI_TO_TCHAR(__FUNCTION__));
ResolvedRunMode = FNavigationSystemRunMode::InvalidMode;
}
if (NewWorld->GetNavigationSystem())
{
NewWorld->GetNavigationSystem()->InitializeForWorld(*NewWorld, ResolvedRunMode);
}*/
//else if (ResolvedRunMode == FNavigationSystemRunMode::EditorMode)
//{
// DiscardNavigationDataChunks(WorldOwner);
//}
FURL URL;
//FURL URL(&WorldContext.LastURL, *NewWorld->GetFName().ToString(), ETravelType::TRAVEL_Absolute);
//URL.AddOption(TEXT("GAME=/Game/ThirdPersonCPP/Blueprints/BpGameMode2.BpGameMode2_C"));
URL.AddOption(TEXT("GAME=/Game/Blueprints/GameModeBP_CreatedWorld.GameModeBP_CreatedWorld_C"));
WorldContext.World()->SetGameMode(URL);
//WorldContext.World()->CreateAISystem();
WorldContext.World()->InitializeActorsForPlay(URL);
//AActor* lacder = nullptr;
for (auto actor : NewWorld->PersistentLevel->Actors) {
UE_LOG(LogTemp, Warning, TEXT("LoadedWorldActorsClasses: %s"), *UKismetSystemLibrary::GetDisplayName(actor));
//if (actor->GetClass()->GetName() == "BpGameMode2_C")
//{
// //lacder = actor;
//}
}
UFunction* Func = NewWorld->GetAuthGameMode()->GetClass()->FindFunctionByName(FName("Load"));
if (Func == nullptr) {
return;
}
FStructOnScope FuncParam(Func);
NewWorld->GetAuthGameMode()->ProcessEvent(Func, FuncParam.GetStructMemory());
//UNavigationSystemV1 *NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(NewWorld);
//if (NavSys)
//{
// ANavigationData *UseNavData = NavSys->GetDefaultNavDataInstance(FNavigationSystem::Create);
// NavSys->Build();
//}
WorldContext.World()->BeginPlay();
WorldContext.World()->bWorldWasLoadedThisTick = true;
if (!CleanupHandle.IsValid()) {
// Tick call in PIE
TickHandle = FWorldDelegates::OnWorldTickStart.AddLambda([](UWorld* World, ELevelTick TickType, float DeltaSeconds) {
if (World == GetMainWorld() && GetMainWorld()->WorldType == EWorldType::PIE) {
for (auto WorldRef : CreatedWorlds) {
if (WorldRef->ShouldTick())
{
WorldRef->Tick(TickType, DeltaSeconds);
//GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Yellow, FString::Printf(TEXT("TickInWorld: %s"), *WorldRef->GetFName().ToString()));
//UE_LOG(LogTemp, Warning, TEXT("TickInWorld: %s"), *WorldRef->GetFName().ToString());
}
}
}
});
if (TickHandle.IsValid())
{
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Yellow, FString::Printf(TEXT("TickHackSet")));
UE_LOG(LogTemp, Warning, TEXT("TickHackSet"));
}
CleanupHandle = FWorldDelegates::OnPostWorldCleanup.AddLambda([](UWorld *World, bool bSessionEnded, bool bCleanupResources) {
if (!CreatedWorlds.Contains(World)) {
FWorldDelegates::OnPostWorldCleanup.Remove(CleanupHandle);
CleanupHandle.Reset();
if (TickHandle.IsValid()) {
FWorldDelegates::OnWorldTickStart.Remove(TickHandle);
TickHandle.Reset();
}
for (auto WorldRef : CreatedWorlds) {
if (WorldRef) {
auto Name = WorldRef->GetMapName();
for (FActorIterator ActorIt(WorldRef); ActorIt; ++ActorIt)
{
ActorIt->RouteEndPlay(EEndPlayReason::LevelTransition);
}
// Do this after destroying pawns/playercontrollers, in case that spawns new things (e.g. dropped weapons)
//WorldRef->CleanupWorld();
//GEngine->WorldDestroyed(WorldRef);
GEngine->DestroyWorldContext(WorldRef);
WorldRef->DestroyWorld(true);
GEngine->TrimMemory();
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Created World destroyed: %s"), *WorldRef->GetFName().ToString()));
UE_LOG(LogTemp, Warning, TEXT("Created World destroyed: %s"), *Name);
}
}
CreatedWorlds.Empty();
//GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("DestroyedWorld: %s"), *World->GetFName().ToString()));
UE_LOG(LogTemp, Warning, TEXT("DestroyedWorld: %s"), *World->GetFName().ToString());
}
});
}
CreatedWorlds.Add(NewWorld);
UWorldContext.SetWorldContext(&WorldContext);
////World = NewWorld;
//UWorldContext.SetWorldContext(&WorldContext);
//
//auto vp = World->GetGameViewport();
//if (vp) {
// GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Exist viewport")));
// //World->GetGameViewport()->Init(WorldContext, GameInstance);
// GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Player: %d"), World->GetAuthGameMode()->GetNumPlayers()));
//}
//else
//{
// GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("No viewport")));
//}
//GEngine->GameViewport->Viewport->;
FViewportClient* Client = GEngine->GameViewport->Viewport->GetClient();
//Client->
//FViewport::SetViewportClient;
}
void UGameBFL::CreateNewWorld_OLD(const UObject* WorldContextObject, FString LevelName, const TSoftObjectPtr<UWorld> Level, UWorld*& World)
{
//
// UWorld* NewWorld = nullptr;
//
//
//
// {
// const FString LevelName2 = FPackageName::ObjectPathToPackageName(FString("/Game/Maps/TetsMultiWorld/CharacterViewLevel.CharacterViewLevel")); //"/Game/ThirdPersonCPP/Maps/Map3"
// //GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("level name = %s"), *LevelName2));
//
// UPackage* WorldPackage = FindPackage(nullptr, *LevelName2);
// if (WorldPackage == nullptr)
// {
// WorldPackage = LoadPackage(nullptr, *LevelName2, ELoadFlags::LOAD_None);
// if (!WorldPackage)
// {
// GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Package not loaded")));
// return;
// }
//
// }
//
// UWorld* PackageWorld = UWorld::FindWorldInPackage(WorldPackage);
//
// for (auto actor : PackageWorld->PersistentLevel->Actors) {
// UE_LOG(LogTemp, Warning, TEXT("DestroyedWorld: %s"), *actor->GetClass()->GetName());
//
// }
//
//
// }
//
//
//
// // Create new UWorld, ULevel and UModel.
// //const FString WorldNameString = (!LevelName.IsEmpty()) ? LevelName2 : TEXT("Untitled");
// //NewWorld = NewObject<UWorld>(WorldPackage, *WorldNameString);
// //NewWorld->SetFlags(RF_Transactional);
// //NewWorld->FeatureLevel = ERHIFeatureLevel::Num;
//
//
// //NewWorld = UWorld::CreateWorld(EWorldType::PIE, true, FName(*LevelName));
// NewWorld = CreateWorld(EWorldType::PIE, true, FName(*LevelName));
//
//
//
//
//
//
// //Enable tick?????????
// NewWorld->SetShouldTick(true);
//
// FWorldContext& WorldContext = GEngine->CreateNewWorldContext(EWorldType::Game);
// WorldContext.OwningGameInstance = UGameplayStatics::GetGameInstance(WorldContextObject);
// WorldContext.SetCurrentWorld(NewWorld);
//
// WorldContext.World()->SetGameInstance(WorldContext.OwningGameInstance);
//
// //NewWorld->WorldType = WorldContext.WorldType;
//
//
//
// //// In the PIE case the world will already have been initialized as part of CreatePIEWorldByDuplication
// if (!WorldContext.World()->bIsWorldInitialized)
// {
// WorldContext.World()->InitWorld();
// }
//
//
//
// FURL URL;
// //FURL URL(&WorldContext.LastURL, *NewWorld->GetFName().ToString(), ETravelType::TRAVEL_Absolute);
// //URL.AddOption(TEXT("GAME=/Game/ThirdPersonCPP/Blueprints/BpGameMode2.BpGameMode2_C"));
// URL.AddOption(TEXT("GAME=/Game/Blueprints/GameModeBP_CreatedWorld.GameModeBP_CreatedWorld_C"));
// WorldContext.World()->SetGameMode(URL);
//
//
// //WorldContext.World()->CreateAISystem();
//
//
//
//
//
// WorldContext.World()->InitializeActorsForPlay(URL);
//
// for (auto actor : NewWorld->PersistentLevel->Actors) {
// UE_LOG(LogTemp, Warning, TEXT("LoadedWorldActorsClasses: %s"), *UKismetSystemLibrary::GetDisplayName(actor));
// //if (actor->GetClass()->GetName() == "BpGameMode2_C")
// //{
// // //lacder = actor;
// //}
// }
//
//
//
// WorldContext.World()->BeginPlay();
// WorldContext.World()->bWorldWasLoadedThisTick = true;
//
//
//
// if (!CleanupHandle.IsValid()) {
//
// // Tick call in PIE
// FWorldDelegates::OnWorldTickStart.AddLambda([](UWorld* World, ELevelTick TickType, float DeltaSeconds) {
// if (World == GetMainWorld() && GetMainWorld()->WorldType == EWorldType::PIE) {
// for (auto WorldRef : CreatedWorlds) {
// if (WorldRef == World && World->ShouldTick()) {
// WorldRef->Tick(TickType, DeltaSeconds);
// //GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Yellow, FString::Printf(TEXT("TickInWorld: %s"), *WorldRef->GetFName().ToString()));
// //UE_LOG(LogTemp, Warning, TEXT("TickInWorld: %s"), *WorldRef->GetFName().ToString());
// }
// }
// }
// });
//
//
// CleanupHandle = FWorldDelegates::OnPostWorldCleanup.AddLambda([](UWorld* World, bool bSessionEnded, bool bCleanupResources) {
// if (!CreatedWorlds.Contains(World)) {
// FWorldDelegates::OnPostWorldCleanup.Remove(CleanupHandle);
// CleanupHandle.Reset();
//
// for (auto WorldRef : CreatedWorlds) {
// auto Name = WorldRef->GetMapName();
// for (FActorIterator ActorIt(WorldRef); ActorIt; ++ActorIt)
// {
// ActorIt->RouteEndPlay(EEndPlayReason::LevelTransition);
// }
//
// // Do this after destroying pawns/playercontrollers, in case that spawns new things (e.g. dropped weapons)
// //WorldRef->CleanupWorld();
//
// //GEngine->WorldDestroyed(WorldRef);
//
//
//
// GEngine->DestroyWorldContext(WorldRef);
// WorldRef->DestroyWorld(true);
//
// GEngine->TrimMemory();
// //GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("Created World destroyed: %s"), *WorldRef->GetFName().ToString()));
// UE_LOG(LogTemp, Warning, TEXT("Created World destroyed: %s"), *Name);
// }
// CreatedWorlds.Empty();
//
// //GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("DestroyedWorld: %s"), *World->GetFName().ToString()));
// UE_LOG(LogTemp, Warning, TEXT("DestroyedWorld: %s"), *World->GetFName().ToString());
// }
// });
// }
//
//
// CreatedWorlds.Add(NewWorld);
// World = NewWorld;
//
//
//
//
//
// //FTimerDelegate TimerCallback;
// //TimerCallback.BindLambda([WorldContext, NewWorld]
// //{
// // for (FActorIterator ActorIt(WorldContext.World()); ActorIt; ++ActorIt)
// // {
// // ActorIt->RouteEndPlay(EEndPlayReason::LevelTransition);
// // }
//
// // // Do this after destroying pawns/playercontrollers, in case that spawns new things (e.g. dropped weapons)
// // WorldContext.World()->CleanupWorld();
//
// // GEngine->WorldDestroyed(WorldContext.World());
//
// // GEngine->DestroyWorldContext(NewWorld);
// // NewWorld->DestroyWorld(true);
//
// // GEngine->TrimMemory();
// // GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, FString::Printf(TEXT("World unloaded")));
// //});
//
// //FTimerHandle Handle;
// //WorldContextObject->GetWorld()->GetTimerManager().SetTimer(Handle, TimerCallback, 5.0f, false);
//
//
//
//
//
//
}
void UGameBFL::WorldBeginPlay(UObject* World)
{
auto NewWorld = Cast<UWorld>(World->GetWorld());
if (NewWorld)
{
NewWorld->BeginPlay();
}
}
UWorld* UGameBFL::CreateWorld(const EWorldType::Type InWorldType, bool bInformEngineOfWorld, FName WorldName, UPackage* InWorldPackage, bool bAddToRoot, ERHIFeatureLevel::Type InFeatureLevel)
{
if (InFeatureLevel >= ERHIFeatureLevel::Num)
{
InFeatureLevel = ERHIFeatureLevel::SM5;
}
UPackage* WorldPackage = InWorldPackage;
if (!WorldPackage)
{
WorldPackage = CreatePackage(nullptr);
}
if (InWorldType == EWorldType::PIE)
{
WorldPackage->SetPackageFlags(PKG_PlayInEditor);
}
// Mark the package as containing a world. This has to happen here rather than at serialization time,
// so that e.g. the referenced assets browser will work correctly.
if (WorldPackage != GetTransientPackage())
{
WorldPackage->ThisContainsMap();
}
// Create new UWorld, ULevel and UModel.
const FString WorldNameString = (WorldName != NAME_None) ? WorldName.ToString() : TEXT("Untitled");
UWorld* NewWorld = NewObject<UWorld>(WorldPackage, *WorldNameString);
NewWorld->SetFlags(RF_Transactional);
NewWorld->WorldType = InWorldType;
NewWorld->FeatureLevel = InFeatureLevel;
NewWorld->InitializeNewWorld(UWorld::InitializationValues()
.ShouldSimulatePhysics(false)
.EnableTraceCollision(true)
.CreateNavigation(true)
.CreateAISystem(true));
// Clear the dirty flag set during SpawnActor and UpdateLevelComponents
WorldPackage->SetDirtyFlag(false);
if (bAddToRoot)
{
// Add to root set so it doesn't get garbage collected.
NewWorld->AddToRoot();
}
// Tell the engine we are adding a world (unless we are asked not to)
if ((GEngine) && (bInformEngineOfWorld == true))
{
GEngine->WorldAdded(NewWorld);
}
return NewWorld;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// World navigation logick //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UGameBFL::CreateNavigationData(UObject* World)
{
auto NewWorld = Cast<UWorld>(World->GetWorld());
if (NewWorld)
{
UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(NewWorld);
if (NavSys)
{
ANavigationData* DefaultData = NavSys->GetDefaultNavDataInstance(FNavigationSystem::DontCreate);
if (DefaultData)
{
//const UNavigationSystemV1::ERegistrationResult Result = NavSys->RegisterNavData(nullptr);
//NavSys->LogNavDataRegistrationResult(Result);
return;
}
ANavigationData* UseNavData = NavSys->GetDefaultNavDataInstance(FNavigationSystem::Create);
ARecastNavMesh* NavMesh = Cast<ARecastNavMesh>(UseNavData);
//if (NavMesh)
//{
// for (TFieldIterator<FProperty> PropertyIterator(NavMesh->GetClass()); PropertyIterator; ++PropertyIterator)
// {
// FProperty* Property = *PropertyIterator;
// FName const PropertyName = Property->GetFName();
// if (PropertyName == "RuntimeGeneration")
// {
// FEnumProperty* prop = Cast<FEnumProperty>(Property);
// if (prop)
// {
// ERuntimeGenerationType* ptrValue = prop->ContainerPtrToValuePtr<ERuntimeGenerationType>(Property);
// prop->GetUnderlyingProperty()->SetIntPropertyValue(ptrValue, prop->GetEnum()->GetValueByIndex(1));
// if (ptrValue)
// {
//
// //int i = (int)(*ptrValue);
// const TEnumAsByte<ERuntimeGenerationType> SurfaceEnum = UseNavData->GetRuntimeGenerationMode();
// FString EnumAsString = UEnum::GetValueAsString(SurfaceEnum.GetValue());
// GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("Val: %s"), *EnumAsString));
// //FTimerDelegate TimerCallback;
// //TimerCallback.BindLambda([UseNavData, i]
// //{
// // const TEnumAsByte<ERuntimeGenerationType> SurfaceEnum = UseNavData->GetRuntimeGenerationMode();
// // FString EnumAsString = UEnum::GetValueAsString(SurfaceEnum.GetValue());
// // GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, FString::Printf(TEXT("Val: %s"), *EnumAsString));
// //});
// //FTimerHandle Handle;
// //World->GetWorld()->GetTimerManager().SetTimer(Handle, TimerCallback, 5.0f, false);
// }
// }
// break;
// }
// }
//}
}
}
}
void UGameBFL::BuildNavigation(UObject* World)
{
auto NewWorld = Cast<UWorld>(World->GetWorld());
if (NewWorld)
{
UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(NewWorld);
if (NavSys)
{
NavSys->Build();
}
}
}
TArray<uint8> UGameBFL::SaveNavData(UObject* World) {
auto NewWorld = Cast<UWorld>(World->GetWorld());
if (NewWorld)
{
UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(NewWorld);
ANavigationData* NavData = NavSys->GetDefaultNavDataInstance(FNavigationSystem::ECreateIfEmpty::DontCreate);
if (NavData) {
ARecastNavMesh* NavMesh = Cast<ARecastNavMesh>(NavData);
//NavMesh->GetGenerator()->ExportNavigationData(FString(TEXT("C:\\Users\\xxxx\\Navmesh")));
return SaveToBinaryArray(NavData, false);
}
}
TArray<uint8> t;
return t;
}
void UGameBFL::LoadNavData(UObject* World, TArray<uint8> data) {
auto NewWorld = Cast<UWorld>(World->GetWorld());
if (NewWorld)
{
UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(NewWorld);
ANavigationData* NavData = NavSys->GetDefaultNavDataInstance(FNavigationSystem::ECreateIfEmpty::DontCreate);
if (NavData) {
ARecastNavMesh* NavMesh = Cast<ARecastNavMesh>(NavData);
LoadFromBinaryArray(data, NavData, false);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// End World logick //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void UGameBFL::ProcessTick(TArray<UObject*> Objects, float DeltaSeconds) {
for (auto Obj : Objects) {
//GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Orange, FString::Printf(TEXT("Tick: %s"), *Obj->GetFName().ToString()));
//Cast<AActor>(Obj)->TickActor(DeltaSeconds, ELevelTick::LEVELTICK_All, nullptr);
Obj->GetWorld()->GetNavigationSystem()->Tick(DeltaSeconds);
}
}