247 lines
6.5 KiB
C++
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();
|
|
}
|
|
}
|