haxis/Source/UnrealProject/GUI/Menu/GameList.cpp

247 lines
6.5 KiB
C++

// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "GameList.h"
#include "GameListItem.h"
#include "DefaultGameInstance.h"
#include "SessionManager.h"
#include "ScreenOverlay.h"
#include "PlayerControllerBase.h"
static UClass* itemWidgetClass;
UGameList::UGameList(const FObjectInitializer& init)
: Super(init)
{
itemWidgetClass = ConstructorHelpers::FClassFinder<UGameListItem>(TEXT("/Game/Assets/GUI/Components/WEEGEE_GameListItem")).Class;
m_quickJoining = false;
}
void UGameList::NativeConstruct()
{
Super::NativeConstruct();
m_searchingSessions = false;
m_joining = false;
UWorld* world = this->GetWorld();
if (!world)
return;
m_gameInstance = Cast<UDefaultGameInstance>(world->GetGameInstance());
if (!m_gameInstance)
return;
onItemSelectionConfirmed.AddDynamic(this, &UGameList::OnListItemPressed);
}
void UGameList::NativeDestruct()
{
m_StopPingingGames();
Super::NativeDestruct();
}
void UGameList::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
{
Super::NativeTick(MyGeometry, InDeltaTime);
}
void UGameList::OnStartSearching_Implementation()
{
}
void UGameList::OnEndSearching_Implementation(int32)
{
}
void UGameList::SetInitialSearchMode_Implementation(bool useLan)
{
}
void UGameList::OnQuickJoin()
{
OnSearchButton();
m_quickJoining = true;
}
void UGameList::JoinSession(const class FOnlineSessionSearchResult& result)
{
m_StopPingingGames();
if(!m_joining)
{
APlayerControllerBase* pc = Cast<APlayerControllerBase>(GetOwningPlayer());
check(!m_joiningOverlay);
m_joiningOverlay = pc->overlay->ShowOverlay("Joining game");
m_joining = true;
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
inst->sessionManager->onJoinSessionComplete.AddUObject(this, &UGameList::m_OnJoinSessionComplete);
inst->sessionManager->JoinSession(result);
}
}
void UGameList::SetSearchMode(bool useLan)
{
}
void UGameList::OnSearchButton()
{
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
if (!m_searchingSessions)
{
check(!m_searchingOverlay);
inst->sessionManager->onFindSessionsComplete.AddUObject(this, &UGameList::m_OnFindSessionsComplete);
inst->sessionManager->FindSessions();
m_searchingSessions = true;
container->ClearChildren();
m_StopPingingGames();
m_gameItems.SetNum(0);
RescanItems();
OnStartSearching();
APlayerControllerBase* pc = Cast<APlayerControllerBase>(GetOwningPlayer());
m_searchingOverlay = pc->overlay->ShowOverlay("Searching for games");
}
}
void UGameList::OnListItemPressed(UMenuItemBase* item)
{
GWPRINT(L"Pressed item " + item);
UGameListItem* listItem = Cast<UGameListItem>(item);
if(listItem)
{
JoinSession(*listItem->result);
}
}
void UGameList::m_OnFindSessionsComplete(bool success)
{
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
// Hide searching overlay
m_searchingOverlay->Close();
m_searchingOverlay = nullptr;
m_searchingSessions = false;
if(!success)
{
APlayerControllerBase* pc = Cast<APlayerControllerBase>(GetOwningPlayer());
TArray<FString> options;
options.Add("OK");
pc->overlay->ShowMessageBox("Error", "Error occured while fining games", options);
return;
}
if(m_quickJoining)
{
// Find session with most players in, that is not full
auto& results = inst->sessionManager->sessionSearch->SearchResults;
if(results.Num() > 0)
{
FOnlineSessionSearchResult* optimal = &results[0];
int32 largest = 0;
for(int32 i = 1; i < results.Num(); i++)
{
const int32 available = results[i].Session.NumOpenPublicConnections;
if(available == 0) continue;
const int32 max = results[i].Session.SessionSettings.NumPublicConnections;
const int32 current = max - available;
if(current > largest)
{
optimal = &results[i];
largest = current;
}
}
JoinSession(*optimal);
}
m_quickJoining = false;
}
else
{
// Get session results
auto& results = inst->sessionManager->sessionSearch->SearchResults;
for(int32 i = 0; i < results.Num(); i++)
{
// Create a selectable slot in the game list
UGameListItem* childItem = CreateWidget<UGameListItem>(GetWorld(), itemWidgetClass);
check(container);
container->AddChild(childItem);
childItem->SetItem(this, results[i]);
m_gameItems.Add(childItem);
}
OnEndSearching(results.Num());
RescanItems();
// Give ping data for games
m_StartPingingGames();
}
m_searchingSessions = false;
// Remove callback
inst->sessionManager->onFindSessionsComplete.RemoveAll(this);
}
void UGameList::m_OnJoinSessionComplete(int32 result)
{
UDefaultGameInstance* inst = Cast<UDefaultGameInstance>(GetGameInstance());
APlayerControllerBase* pc = Cast<APlayerControllerBase>(GetOwningPlayer());
m_joining = false;
// Remove callback
inst->sessionManager->onJoinSessionComplete.RemoveAll(this);
if(result != EOnJoinSessionCompleteResult::Success)
{
FString error = "Unknown";
switch(result)
{
case EOnJoinSessionCompleteResult::AlreadyInSession:
error = "Already in session";
break;
case EOnJoinSessionCompleteResult::CouldNotRetrieveAddress:
error = "Could not retrieve address";
break;
case EOnJoinSessionCompleteResult::SessionDoesNotExist:
error = "Session does not exist";
break;
case EOnJoinSessionCompleteResult::SessionIsFull:
error = "Session is full";
break;
}
// Close joining overlay
m_joiningOverlay->Close();
m_joiningOverlay = nullptr;
// Show error message
TArray<FString> options;
options.Add("OK");
pc->overlay->ShowMessageBox("Error", FString("Failed to join session:\n") + error, options);
}
else
{
// Travel to destination player lobby
pc->ClientTravel(inst->sessionManager->joinConnectionString, ETravelType::TRAVEL_Absolute, false);
//UWorld* world = GetWorld();
//world->SeamlessTravel(inst->sessionManager->joinConnectionString, true);
//world->ServerTravel()
//AMenuGameMode* mgm = Cast<AMenuGameMode>(world->GetAuthGameMode());
}
}
void UGameList::m_PingGames()
{
for(auto& g : m_gameItems)
{
g->Ping();
}
}
void UGameList::m_StartPingingGames()
{
GetGameInstance()->GetTimerManager().SetTimer(m_pinger, this, &UGameList::m_PingGames, 1.0f, true);
}
void UGameList::m_StopPingingGames()
{
GetGameInstance()->GetTimerManager().ClearTimer(m_pinger);
for(UGameListItem* i : m_gameItems)
{
i->Ping();
}
}