I am trying to test out getting multiplayer to work through the steam OSS and can never connect over the net for some reason. Cant find any issue in the code. Tried port forwarding as the host as well and still nothing. I am fairly new to coding so im sure im just missing something simple.
GameInstance.cpp
#include "PuzzlePlatformsGameInstance.h"
#include "Engine/Engine.h"
#include "UObject/ConstructorHelpers.h"
#include "Blueprint/UserWidget.h"
#include "OnlineSessionSettings.h"
#include "PlatformTrigger.h"
#include "MenuSystem/MainMenu.h"
#include "MenuSystem/MenuWidget.h"
const static FName SESSION_NAME = TEXT("Game"); // swapped with NAME_GameSession
const static FName SERVER_NAME_SETTINGS_KEY = TEXT("ServerName");
UPuzzlePlatformsGameInstance::UPuzzlePlatformsGameInstance(const FObjectInitializer & ObjectInitializer)
{
UE_LOG(LogTemp, Warning, TEXT("This is the GameInstance Constructor"));
ConstructorHelpers::FClassFinder<UUserWidget> MenuBPClass(TEXT("/Game/MenuSystem/WBP_MainMenu"));
if (!ensure(MenuBPClass.Class != nullptr)) return;
MenuClass = MenuBPClass.Class;
ConstructorHelpers::FClassFinder<UUserWidget> InGameMenuBPClass(TEXT("/Game/MenuSystem/WBP_InGameMenu"));
if (!ensure(InGameMenuBPClass.Class != nullptr)) return;
InGameMenuClass = InGameMenuBPClass.Class;
}
void UPuzzlePlatformsGameInstance::Init()
{
Super::Init();
IOnlineSubsystem* Subsystem = IOnlineSubsystem::Get();
if (Subsystem != nullptr)
{
UE_LOG(LogTemp, Warning, TEXT("Found subsystem %s"), *Subsystem->GetSubsystemName().ToString());
SessionInterface = Subsystem->GetSessionInterface();
if (SessionInterface.IsValid())
{
UE_LOG(LogTemp, Warning, TEXT("Found session interface"));
SessionInterface->OnCreateSessionCompleteDelegates.AddUObject(this, &UPuzzlePlatformsGameInstance::OnCreateSessionComplete);
SessionInterface->OnDestroySessionCompleteDelegates.AddUObject(this, &UPuzzlePlatformsGameInstance::OnDestroySessionComplete);
SessionInterface->OnFindSessionsCompleteDelegates.AddUObject(this, &UPuzzlePlatformsGameInstance::OnFindSessionsComplete);
SessionInterface->OnJoinSessionCompleteDelegates.AddUObject(this, &UPuzzlePlatformsGameInstance::OnJoinSessionComplete);
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Found no subsystem"));
}
if (GEngine != nullptr)
{
GEngine->OnNetworkFailure().AddUObject(this, &UPuzzlePlatformsGameInstance::OnNetworkFailure);
}
}
void UPuzzlePlatformsGameInstance::LoadMenu()
{
if (!ensure(MenuClass != nullptr)) return;
Menu = CreateWidget<UMainMenu>(this, MenuClass);
if (!ensure(Menu != nullptr)) return;
Menu->Setup();
Menu->SetMenuInterface(this);
}
void UPuzzlePlatformsGameInstance::LoadInGameMenu()
{
if (!ensure(InGameMenuClass != nullptr)) return;
UMenuWidget* MMenu = CreateWidget<UMenuWidget>(this, InGameMenuClass);
if (!ensure(MMenu != nullptr)) return;
MMenu->Setup();
MMenu->SetMenuInterface(this);
MMenu->bIsFocusable = true;
}
void UPuzzlePlatformsGameInstance::Host(FString ServerName)
{
DesiredServerName = ServerName;
if (SessionInterface.IsValid())
{
auto ExistingSession = SessionInterface->GetNamedSession(NAME_GameSession);
if (ExistingSession != nullptr)
{
SessionInterface->DestroySession(NAME_GameSession);
}
else
{
CreateSession();
}
}
}
void UPuzzlePlatformsGameInstance::OnDestroySessionComplete(FName SessionName, bool Success)
{
if (Success)
{
CreateSession();
}
}
void UPuzzlePlatformsGameInstance::OnNetworkFailure(UWorld* World, UNetDriver* NetDriver, ENetworkFailure::Type FailureType, const FString& ErrorString)
{
LoadMainMenu();
}
void UPuzzlePlatformsGameInstance::CreateSession()
{
if (SessionInterface.IsValid())
{
FOnlineSessionSettings SessionSettings;
if (IOnlineSubsystem::Get()->GetSubsystemName() == "NULL")
{
SessionSettings.bIsLANMatch = true;
}
else
{
SessionSettings.bIsLANMatch = false;
}
SessionSettings.NumPublicConnections = 4;
SessionSettings.bShouldAdvertise = true;
SessionSettings.bUsesPresence = true; //uses pressences enables online rather the lan
SessionSettings.Set(SERVER_NAME_SETTINGS_KEY, DesiredServerName, EOnlineDataAdvertisementType::ViaOnlineServiceAndPing);
SessionSettings.bUseLobbiesIfAvailable = true;
// testing these options
//SessionSettings.bAllowInvites = true;
//SessionSettings.bAllowJoinViaPresence = true;
//SessionSettings.bAllowJoinInProgress = true;
SessionInterface->CreateSession(0, NAME_GameSession, SessionSettings);
}
}
void UPuzzlePlatformsGameInstance::OnCreateSessionComplete(FName SessionName, bool Success)
{
if (!Success)
{
UE_LOG(LogTemp, Warning, TEXT("Could Not Create Session!"));
return;
}
if (Menu != nullptr)
{
Menu->Teardown();
}
UEngine* Engine = GetEngine();
if (!ensure(Engine != nullptr)) return;
Engine->AddOnScreenDebugMessage(0, 2.f, FColor::Green, TEXT("Hosting"));
//if (GEngine)
//{
// GEngine->AddOnScreenDebugMessage(0, 2.f, FColor::Green, TEXT("Hosting"));
//}
UWorld* World = GetWorld();
if (!ensure(World != nullptr)) return;
World->ServerTravel("/Game/ThirdPerson/Maps/Lobby?Listen"); //not sure if ETravelType::TRAVEL_Absolute is needed
}
void UPuzzlePlatformsGameInstance::RefreshServerList()
{
SessionSearch = MakeShareable(new FOnlineSessionSearch());
if (SessionSearch.IsValid())
{
//SessionSearch->bIsLanQuery = false;
SessionSearch->MaxSearchResults = 1000000; //caused from sharing apID through steam
SessionSearch->QuerySettings.Set(NAME_GameSession, true, EOnlineComparisonOp::Equals);
UE_LOG(LogTemp, Warning, TEXT("Starting to find Session..."));
SessionInterface->FindSessions(0, SessionSearch.ToSharedRef());
}
}
void UPuzzlePlatformsGameInstance::OnFindSessionsComplete(bool Success)
{
if (Success && SessionSearch.IsValid() && Menu != nullptr)
{
UE_LOG(LogTemp, Warning, TEXT("Finished Finding Session."));
TArray<FServerData> ServerNames;
for (const FOnlineSessionSearchResult& SearchResult : SessionSearch->SearchResults)
{
UE_LOG(LogTemp, Warning, TEXT("Found Session named: %s"), *SearchResult.GetSessionIdStr());
FServerData Data;
//Data.Name = SearchResult.GetSessionIdStr();
Data.MaxPlayers = SearchResult.Session.SessionSettings.NumPublicConnections;
Data.CurrentPlayers = Data.MaxPlayers - SearchResult.Session.NumOpenPublicConnections;
Data.HostUserName = SearchResult.Session.OwningUserName;
FString ServerName;
if (SearchResult.Session.SessionSettings.Get(SERVER_NAME_SETTINGS_KEY, ServerName))
{
Data.Name = ServerName;
}
else
{
Data.Name = "Could not get servername";
}
ServerNames.Add(Data);
}
Menu->SetServerList(ServerNames);
}
}
void UPuzzlePlatformsGameInstance::Join(uint32 Index)
{
if (!SessionInterface.IsValid()) return;
if (!SessionSearch.IsValid()) return;
if (Menu != nullptr)
{
Menu->Teardown();
}
SessionInterface->JoinSession(0, NAME_GameSession, SessionSearch->SearchResults[Index]);
}
void UPuzzlePlatformsGameInstance::OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result)
{
if (!SessionInterface.IsValid()) return;
FString Address;
if (!SessionInterface->GetResolvedConnectString(SessionName, Address))
{
UE_LOG(LogTemp, Warning, TEXT("Could not get connect string"));
return;
}
UEngine* Engine = GetEngine();
if (!ensure(Engine != nullptr)) return;
Engine->AddOnScreenDebugMessage(0, 5.f, FColor::Green, FString::Printf(TEXT("Joining %s"), *Address));
//if (GEngine)
//{
// GEngine->AddOnScreenDebugMessage(0, 5.f, FColor::Green, FString::Printf(TEXT("Joining %s"), *Address));
//}
APlayerController* PlayerController = GetFirstLocalPlayerController();
if (!ensure(PlayerController != nullptr)) return;
PlayerController->ClientTravel(Address, ETravelType::TRAVEL_Absolute);
}
void UPuzzlePlatformsGameInstance::StartSession()
{
if (SessionInterface.IsValid())
{
SessionInterface->StartSession(NAME_GameSession);
}
}
void UPuzzlePlatformsGameInstance::LoadMainMenu()
{
APlayerController* PlayerController = GetFirstLocalPlayerController();
if (!ensure(PlayerController != nullptr)) return;
PlayerController->ClientTravel("/Game/MenuSystem/MainMenu", ETravelType::TRAVEL_Absolute);
}
GameInstance.h
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "OnlineSubsystem.h"
#include "MenuSystem/MenuInterface.h"
#include "Interfaces/OnlineSessionInterface.h"
#include "PuzzlePlatformsGameInstance.generated.h"
/**
*
*/
UCLASS()
class PUZZLEPLATFORMS_API UPuzzlePlatformsGameInstance : public UGameInstance, public IMenuInterface
{
GENERATED_BODY()
public:
UPuzzlePlatformsGameInstance
(
const FObjectInitializer & ObjectInitializer
);
void Init();
UFUNCTION(BlueprintCallable)
void LoadMenu();
UFUNCTION(BlueprintCallable)
void LoadInGameMenu();
UFUNCTION(Exec)
void Host(FString ServerName) override;
UFUNCTION(Exec)
void Join(uint32 Index) override;
void StartSession();
virtual void LoadMainMenu() override;
void RefreshServerList() override;
private:
TSubclassOf<class UUserWidget> MenuClass;
TSubclassOf<class UUserWidget> InGameMenuClass;
class UMainMenu* Menu;
IOnlineSessionPtr SessionInterface;
TSharedPtr<class FOnlineSessionSearch> SessionSearch;
void OnCreateSessionComplete(FName SessionName, bool Success);
void OnDestroySessionComplete(FName SessionName, bool Success);
void OnFindSessionsComplete(bool Success);
void OnJoinSessionComplete(FName SessionName, EOnJoinSessionCompleteResult::Type Result);
void OnNetworkFailure(UWorld* World, UNetDriver* NetDriver, ENetworkFailure::Type FailureType, const FString& ErrorString);
FString DesiredServerName;
void CreateSession();
};
MainMenu.cpp
#include "MainMenu.h"
#include "UObject/ConstructorHelpers.h"
#include "Components/Button.h"
#include "Components/WidgetSwitcher.h"
#include "Components/EditableText.h"
#include "Components/TextBlock.h"
#include "Components/EditableTextBox.h"
#include "ServerRow.h"
UMainMenu::UMainMenu(const FObjectInitializer & ObjectInitializer)
{
ConstructorHelpers::FClassFinder<UUserWidget> ServerRowBPClass(TEXT("/Game/MenuSystem/WBP_ServerRow"));
if (!ensure(ServerRowBPClass.Class != nullptr)) return;
ServerRowClass = ServerRowBPClass.Class;
}
bool UMainMenu::Initialize()
{
bool Success = Super::Initialize();
if (!Success) return false;
if (!ensure(HostButton != nullptr)) return false;
HostButton->OnClicked.AddDynamic(this, &UMainMenu::OpenHostMenu);
if (!ensure(CancelHostMenuButton != nullptr)) return false;
CancelHostMenuButton->OnClicked.AddDynamic(this, &UMainMenu::OpenMainMenu);
if (!ensure(ConfirmHostMenuButton != nullptr)) return false;
ConfirmHostMenuButton->OnClicked.AddDynamic(this, &UMainMenu::HostServer);
if (!ensure(JoinButton != nullptr)) return false;
JoinButton->OnClicked.AddDynamic(this, &UMainMenu::OpenJoinMenu);
if (!ensure(ExitButton != nullptr)) return false;
ExitButton->OnClicked.AddDynamic(this, &UMainMenu::ExitPressed);
if (!ensure(CancelJoinMenuButton != nullptr)) return false;
CancelJoinMenuButton->OnClicked.AddDynamic(this, &UMainMenu::OpenMainMenu);
if (!ensure(ConfirmJoinMenuButton != nullptr)) return false;
ConfirmJoinMenuButton->OnClicked.AddDynamic(this, &UMainMenu::JoinServer);
return true;
}
void UMainMenu::OpenHostMenu()
{
MenuSwitcher->SetActiveWidget(HostMenu);
}
void UMainMenu::HostServer()
{
if (MMenuInterface != nullptr)
{
FString ServerName = ServerHostName->Text.ToString();
MMenuInterface->Host(ServerName);
}
}
void UMainMenu::SetServerList(TArray<FServerData> ServerNames)
{
UWorld* World = this->GetWorld();
if (!ensure(World != nullptr)) return;
ServerList->ClearChildren();
uint32 i = 0;
for (const FServerData& ServerData : ServerNames)
{
if (!ensure(ServerRowClass != nullptr)) return;
UServerRow* Row = CreateWidget<UServerRow>(World, ServerRowClass);
if (!ensure(Row != nullptr)) return;
Row->ServerName->SetText(FText::FromString(ServerData.Name));
Row->HostUser->SetText(FText::FromString(ServerData.HostUserName));
Row->ConnectionFraction->SetText(FText::FromString(FString::Printf(TEXT("%d/%d"), ServerData.CurrentPlayers, ServerData.MaxPlayers)));
Row->Setup(this, i);
++i;
ServerList->AddChild(Row);
}
}
void UMainMenu::SelectIndex(uint32 Index)
{
SelectedIndex = Index;
UpdateChildren(); //updates the server rows
}
void UMainMenu::UpdateChildren()
{
for (int32 i = 0; i < ServerList->GetChildrenCount(); ++i)
{
UServerRow* Row = Cast<UServerRow>(ServerList->GetChildAt(i));
if (Row != nullptr)
{
Row->Selected = (SelectedIndex.IsSet() && SelectedIndex.GetValue() == i);
}
}
}
void UMainMenu::JoinServer()
{
if (SelectedIndex.IsSet() && MMenuInterface != nullptr)
{
UE_LOG(LogTemp, Warning, TEXT("Selected index %d"), SelectedIndex.GetValue());
MMenuInterface->Join(SelectedIndex.GetValue());
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Selected index not set!"));
}
}
void UMainMenu::OpenJoinMenu()
{
if (!ensure(MenuSwitcher != nullptr)) return;
if (!ensure(JoinMenu != nullptr)) return;
MenuSwitcher->SetActiveWidget(JoinMenu);
if (MMenuInterface != nullptr)
{
MMenuInterface->RefreshServerList();
}
}
void UMainMenu::OpenMainMenu()
{
if (!ensure(MenuSwitcher != nullptr)) return;
if (!ensure(MainMenu != nullptr)) return;
MenuSwitcher->SetActiveWidget(MainMenu);
}
void UMainMenu::ExitPressed()
{
UWorld* World = GetWorld();
if (!ensure(World != nullptr)) return;
APlayerController* PlayerController = World->GetFirstPlayerController();
if (!ensure(PlayerController != nullptr)) return;
PlayerController->ConsoleCommand("quit");
}
MainMenu.h
#pragma once
#include "CoreMinimal.h"
#include "MenuWidget.h"
#include "MainMenu.generated.h"
USTRUCT()
struct FServerData
{
GENERATED_BODY()
FString Name;
uint16 CurrentPlayers;
uint16 MaxPlayers;
FString HostUserName;
};
/**
*
*/
UCLASS()
class PUZZLEPLATFORMS_API UMainMenu : public UMenuWidget
{
GENERATED_BODY()
public:
UMainMenu(const FObjectInitializer & ObjectInitializer);
void SetServerList(TArray<FServerData> ServerNames);
void SelectIndex(uint32 Index);
protected:
virtual bool Initialize();
private:
TSubclassOf<class UUserWidget> ServerRowClass;
UPROPERTY(meta = (BindWidget))
class UButton* HostButton;
UPROPERTY(meta = (BindWidget))
class UButton* JoinButton;
UPROPERTY(meta = (BindWidget))
class UButton* ExitButton;
UPROPERTY(meta = (BindWidget))
class UButton* CancelJoinMenuButton;
UPROPERTY(meta = (BindWidget))
class UButton* ConfirmJoinMenuButton;
UPROPERTY(meta = (BindWidget))
class UWidgetSwitcher* MenuSwitcher;
UPROPERTY(meta = (BindWidget))
class UWidget* JoinMenu;
UPROPERTY(meta = (BindWidget))
class UWidget* MainMenu;
UPROPERTY(meta = (BindWidget))
class UWidget* HostMenu;
UPROPERTY(meta = (BindWidget))
class UEditableTextBox* ServerHostName;
UPROPERTY(meta = (BindWidget))
class UButton* CancelHostMenuButton;
UPROPERTY(meta = (BindWidget))
class UButton* ConfirmHostMenuButton;
UPROPERTY(meta = (BindWidget))
class UPanelWidget* ServerList;
UFUNCTION()
void HostServer();
UFUNCTION()
void JoinServer();
UFUNCTION()
void OpenHostMenu();
UFUNCTION()
void OpenJoinMenu();
UFUNCTION()
void OpenMainMenu();
UFUNCTION()
void ExitPressed();
TOptional<uint32> SelectedIndex;
void UpdateChildren();
};