// 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(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(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(GetOwningPlayer()); check(!m_joiningOverlay); m_joiningOverlay = pc->overlay->ShowOverlay("Joining game"); m_joining = true; UDefaultGameInstance* inst = Cast(GetGameInstance()); inst->sessionManager->onJoinSessionComplete.AddUObject(this, &UGameList::m_OnJoinSessionComplete); inst->sessionManager->JoinSession(result); } } void UGameList::SetSearchMode(bool useLan) { } void UGameList::OnSearchButton() { UDefaultGameInstance* inst = Cast(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(GetOwningPlayer()); m_searchingOverlay = pc->overlay->ShowOverlay("Searching for games"); } } void UGameList::OnListItemPressed(UMenuItemBase* item) { GWPRINT(L"Pressed item " + item); UGameListItem* listItem = Cast(item); if(listItem) { JoinSession(*listItem->result); } } void UGameList::m_OnFindSessionsComplete(bool success) { UDefaultGameInstance* inst = Cast(GetGameInstance()); // Hide searching overlay m_searchingOverlay->Close(); m_searchingOverlay = nullptr; m_searchingSessions = false; if(!success) { APlayerControllerBase* pc = Cast(GetOwningPlayer()); TArray 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(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(GetGameInstance()); APlayerControllerBase* pc = Cast(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 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(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(); } }