Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
slonopotamus committed Aug 5, 2024
1 parent 4ccfc41 commit a1a7182
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 0 deletions.
82 changes: 82 additions & 0 deletions Source/UEST/Private/ScopedGame.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "ScopedGame.h"

#include "GameMapsSettings.h"

FScopedGameInstance::FScopedGameInstance(TSubclassOf<UGameInstance> GameInstanceClass)
: GameInstanceClass{MoveTemp(GameInstanceClass)}
{
}

FScopedGameInstance::FScopedGameInstance(FScopedGameInstance&& Other)
: GameInstanceClass{MoveTemp(Other.GameInstanceClass)}
, Games{MoveTemp(Other.Games)}
{
}

FScopedGameInstance::~FScopedGameInstance()
{
for (const auto& Game : Games)
{
DestroyGameInternal(*Game);
}
}

UGameInstance& FScopedGameInstance::CreateGame()
{
auto Result = NewObject<UGameInstance>(GEngine, GameInstanceClass);
Games.Emplace(Result);
Result->InitializeStandalone();
return *Result;
}

void FScopedGameInstance::DestroyGameInternal(UGameInstance& Game)
{
Game.Shutdown();
Game.GetWorld()->DestroyWorld(true);
GEngine->DestroyWorldContext(Game.GetWorld());
}

bool FScopedGameInstance::DestroyGame(UGameInstance& Game)
{
for (int32 Index = 0; Index < Games.Num(); ++Index)
{
if (Games[Index].Get() != &Game)
{
continue;
}

DestroyGameInternal(Game);
Games.RemoveAt(Index);

return true;
}

return ensureMsgf(false, TEXT("Game %s was not registered"), *Game.GetPathName());
}

void FScopedGameInstance::Tick(const float DeltaSeconds, const float Step, const ELevelTick TickType)
{
StaticTick(DeltaSeconds);

auto TimeLeftToTick = DeltaSeconds;
while (TimeLeftToTick > 0)
{
const float CurrentStep = FMath::Min(TimeLeftToTick, Step);
TimeLeftToTick -= CurrentStep;
for (const auto& Game : Games)
{
Game->GetWorld()->Tick(TickType, CurrentStep);
}
}
}

FScopedGame& FScopedGame::WithProjectGameInstance()
{
return WithGameInstance(GetDefault<UGameMapsSettings>()->GameInstanceClass.TryLoadClass<UGameInstance>());
}

FScopedGameInstance FScopedGame::Build() const
{
FScopedGameInstance Result{GameInstanceClass};
return MoveTemp(Result);
}
9 changes: 9 additions & 0 deletions Source/UEST/Private/ScopedGameTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "ScopedGame.h"
#include "UEST.h"

TEST(UEST, ScopedGame, Simple)
{
auto Tester = FScopedGame().Build();
auto& Game = Tester.CreateGame();
Tester.DestroyGame(Game);
}
41 changes: 41 additions & 0 deletions Source/UEST/Public/ScopedGame.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include "Engine/GameInstance.h"

class FScopedGameInstance : FNoncopyable
{
TSubclassOf<UGameInstance> GameInstanceClass;

TArray<TStrongObjectPtr<UGameInstance>> Games;

static void DestroyGameInternal(UGameInstance& Game);

public:
FScopedGameInstance(TSubclassOf<UGameInstance> GameInstanceClass);

FScopedGameInstance(FScopedGameInstance&& Other);

virtual ~FScopedGameInstance();

UGameInstance& CreateGame();
bool DestroyGame(UGameInstance& Game);

/** Advances time in all created games by DeltaSeconds in Step increments */
void Tick(float DeltaSeconds, float Step, ELevelTick TickType = LEVELTICK_All);
};

class FScopedGame
{
TSubclassOf<UGameInstance> GameInstanceClass = UGameInstance::StaticClass();

public:
FScopedGame& WithGameInstance(TSubclassOf<UGameInstance> InGameInstanceClass)
{
GameInstanceClass = MoveTemp(InGameInstanceClass);
return *this;
}

FScopedGame& WithProjectGameInstance();

FScopedGameInstance Build() const;
};

0 comments on commit a1a7182

Please sign in to comment.