diff --git a/Content/MainMenu/BP_MainMenuGameMode.uasset b/Content/MainMenu/BP_MainMenuGameMode.uasset index 0f7a079..e269c55 100644 Binary files a/Content/MainMenu/BP_MainMenuGameMode.uasset and b/Content/MainMenu/BP_MainMenuGameMode.uasset differ diff --git a/Content/MainMenu/BP_MainMenuPlayerController.uasset b/Content/MainMenu/BP_MainMenuPlayerController.uasset index 4a59f6f..caf849d 100644 Binary files a/Content/MainMenu/BP_MainMenuPlayerController.uasset and b/Content/MainMenu/BP_MainMenuPlayerController.uasset differ diff --git a/Content/MainMenu/BP_SessionListEntry.uasset b/Content/MainMenu/BP_SessionListEntry.uasset new file mode 100644 index 0000000..36dc2c5 Binary files /dev/null and b/Content/MainMenu/BP_SessionListEntry.uasset differ diff --git a/Content/MainMenu/BP_SessionListMenu.uasset b/Content/MainMenu/BP_SessionListMenu.uasset new file mode 100644 index 0000000..0f1b13f Binary files /dev/null and b/Content/MainMenu/BP_SessionListMenu.uasset differ diff --git a/Content/MainMenu/MainMenu.uasset b/Content/MainMenu/MainMenu.uasset index e409e8c..ae87ceb 100644 Binary files a/Content/MainMenu/MainMenu.uasset and b/Content/MainMenu/MainMenu.uasset differ diff --git a/Content/MainMenu/MainMenuLevel.umap b/Content/MainMenu/MainMenuLevel.umap index 533adf3..da732e9 100644 Binary files a/Content/MainMenu/MainMenuLevel.umap and b/Content/MainMenu/MainMenuLevel.umap differ diff --git a/Content/MainMenu/fotor-ai-2023050222244.uasset b/Content/MainMenu/fotor-ai-2023050222244.uasset index d0de5c1..7145ff0 100644 Binary files a/Content/MainMenu/fotor-ai-2023050222244.uasset and b/Content/MainMenu/fotor-ai-2023050222244.uasset differ diff --git a/Source/TurnBasedTutorial/MyGameInstanceSubsystem.cpp b/Source/TurnBasedTutorial/MyGameInstanceSubsystem.cpp index 4f8f813..3976783 100644 --- a/Source/TurnBasedTutorial/MyGameInstanceSubsystem.cpp +++ b/Source/TurnBasedTutorial/MyGameInstanceSubsystem.cpp @@ -3,6 +3,7 @@ #include "MyGameInstanceSubsystem.h" #include "OnlineSubsystemUtils.h" +#include "Kismet/GameplayStatics.h" UMyGameInstanceSubsystem::UMyGameInstanceSubsystem() : CreateSessionCompleteDelegate( FOnCreateSessionCompleteDelegate::CreateUObject( @@ -45,7 +46,6 @@ void UMyGameInstanceSubsystem::CreateSession(int32 NumPublicConnections, bool bI LastSessionSettings->bAllowJoinInProgress = true; LastSessionSettings->bAllowJoinViaPresence = true; LastSessionSettings->bAllowJoinViaPresenceFriendsOnly = true; - LastSessionSettings->bIsDedicated = false; LastSessionSettings->bUsesPresence = true; LastSessionSettings->bIsLANMatch = bIsLANMatch; LastSessionSettings->bShouldAdvertise = true; @@ -147,8 +147,10 @@ void UMyGameInstanceSubsystem::OnStartSessionCompleted(FName SessionName, bool b { SessionInterface->ClearOnStartSessionCompleteDelegate_Handle(StartSessionCompleteDelegateHandle); } - OnStartSessionCompleteEvent.Broadcast(bSuccessful); + + // TODO: Move this from gameinstance subsystem. This should not be here. + UGameplayStatics::OpenLevel(GetWorld(),"BattleFieldMap", true, "listen"); } @@ -235,7 +237,7 @@ void UMyGameInstanceSubsystem::FindSessions(int32 MaxSearchResults, bool bIsLANQ LastSessionSearch->bIsLanQuery = bIsLANQuery; // Disable dedicated server search (maybe enable later, when dedicated server is implemented) - LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals); + // LastSessionSearch->QuerySettings.Set(SEARCH_PRESENCE, true, EOnlineComparisonOp::Equals); const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); if (!SessionInterface->FindSessions(*LocalPlayer->GetPreferredUniqueNetId(), LastSessionSearch.ToSharedRef())) @@ -286,6 +288,33 @@ void UMyGameInstanceSubsystem::JoinSession(const FOnlineSessionSearchResult& Ses } } +void UMyGameInstanceSubsystem::JoinSession(const int32 Index) +{ + const IOnlineSessionPtr SessionInterface = Online::GetSessionInterface(GetWorld()); + if (!SessionInterface.IsValid()) + { + OnJoinSessionCompleteEvent.Broadcast(EOnJoinSessionCompleteResult::UnknownError); + return; + } + if (!LastSessionSearch.IsValid() || Index >= LastSessionSearch->SearchResults.Num()) + { + OnJoinSessionCompleteEvent.Broadcast(EOnJoinSessionCompleteResult::UnknownError); + return; + } + + JoinSessionCompleteDelegateHandle = SessionInterface->AddOnJoinSessionCompleteDelegate_Handle( + JoinSessionCompleteDelegate); + + const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController(); + if (!SessionInterface->JoinSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, + LastSessionSearch->SearchResults[Index])) + { + SessionInterface->ClearOnJoinSessionCompleteDelegate_Handle(JoinSessionCompleteDelegateHandle); + + OnJoinSessionCompleteEvent.Broadcast(EOnJoinSessionCompleteResult::UnknownError); + } +} + void UMyGameInstanceSubsystem::OnJoinSessionCompleted(FName SessionName, EOnJoinSessionCompleteResult::Type Result) { diff --git a/Source/TurnBasedTutorial/MyGameInstanceSubsystem.h b/Source/TurnBasedTutorial/MyGameInstanceSubsystem.h index 7ad7735..10dbc5b 100644 --- a/Source/TurnBasedTutorial/MyGameInstanceSubsystem.h +++ b/Source/TurnBasedTutorial/MyGameInstanceSubsystem.h @@ -48,6 +48,10 @@ public: void JoinSession(const FOnlineSessionSearchResult& SessionSearchResult); + void JoinSession(const int32 Index); + + bool TryConnectToCurrentSession() const; + FMyOnCreateSessionComplete OnCreateSessionCompleteEvent; FMyOnUpdateSessionComplete OnUpdateSessionCompleteEvent; FMyOnStartSessionCompete OnStartSessionCompleteEvent; @@ -71,8 +75,6 @@ protected: void OnJoinSessionCompleted(FName SessionName, EOnJoinSessionCompleteResult::Type Result); - bool TryConnectToCurrentSession() const; - private: FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate; FDelegateHandle CreateSessionCompleteDelegateHandle; diff --git a/Source/TurnBasedTutorial/MyMainMenu.cpp b/Source/TurnBasedTutorial/MyMainMenu.cpp new file mode 100644 index 0000000..a80d116 --- /dev/null +++ b/Source/TurnBasedTutorial/MyMainMenu.cpp @@ -0,0 +1,35 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MyMainMenu.h" + +#include "Components/Button.h" +#include "Kismet/GameplayStatics.h" + +void UMyMainMenu::NativeConstruct() +{ + Super::NativeConstruct(); + + HostOnlineGameButton->OnClicked.AddDynamic(this, &ThisClass::UMyMainMenu::OnHostOnlineGameButtonClicked); + + GetMyGameSubsystem()->OnCreateSessionCompleteEvent.AddDynamic(this, &ThisClass::StartSessionWhenCreatingSessonComplete); +} + +void UMyMainMenu::OnHostOnlineGameButtonClicked() +{ + GetMyGameSubsystem()->CreateSession(2, true); +} + +void UMyMainMenu::StartSessionWhenCreatingSessonComplete(bool bSuccess) +{ + GetMyGameSubsystem()->StartSession(); +} + + +UMyGameInstanceSubsystem* UMyMainMenu::GetMyGameSubsystem() const +{ + const UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(GetWorld()); + UMyGameInstanceSubsystem* GameInstanceSubsystem = GameInstance->GetSubsystem(); + return GameInstanceSubsystem; +} + diff --git a/Source/TurnBasedTutorial/MyMainMenu.h b/Source/TurnBasedTutorial/MyMainMenu.h new file mode 100644 index 0000000..f316b9f --- /dev/null +++ b/Source/TurnBasedTutorial/MyMainMenu.h @@ -0,0 +1,34 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Blueprint/UserWidget.h" +#include "MyGameInstanceSubsystem.h" + +#include "MyMainMenu.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API UMyMainMenu : public UUserWidget +{ + GENERATED_BODY() + +public: + UPROPERTY(meta = (BindWidget)) + class UButton* HostOnlineGameButton; + + virtual void NativeConstruct() override; + +protected: + UFUNCTION() + void OnHostOnlineGameButtonClicked(); + + UFUNCTION() + void StartSessionWhenCreatingSessonComplete(bool bSuccess); + +private: + UMyGameInstanceSubsystem* GetMyGameSubsystem() const; +}; diff --git a/Source/TurnBasedTutorial/MySessionListEntryWidget.cpp b/Source/TurnBasedTutorial/MySessionListEntryWidget.cpp new file mode 100644 index 0000000..da10049 --- /dev/null +++ b/Source/TurnBasedTutorial/MySessionListEntryWidget.cpp @@ -0,0 +1,22 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MySessionListEntryWidget.h" + +#include "OnlineSessionSettings.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "Components/TextBlock.h" + +void UMySessionListEntryWidget::Update(int SessionIndex, const FOnlineSessionSearchResult& Session) +{ + SessionId = SessionIndex; + IndexText->SetText(FText::AsNumber(SessionIndex + 1)); + // TODO: SessionNameText->SetText(FText::FromString(Session.Session.SessionSettings.Get(...))) + SessionNameText->SetText(FText::FromString("Test session name")); + + int MaxPlayerCount = Session.Session.SessionSettings.NumPublicConnections; + int CurPlayerCount = MaxPlayerCount - Session.Session.NumOpenPublicConnections; + + PlayersCountText->SetText(FText::AsNumber(CurPlayerCount)); + PingText->SetText(FText::AsNumber(Session.PingInMs)); +} diff --git a/Source/TurnBasedTutorial/MySessionListEntryWidget.h b/Source/TurnBasedTutorial/MySessionListEntryWidget.h new file mode 100644 index 0000000..d6c3b31 --- /dev/null +++ b/Source/TurnBasedTutorial/MySessionListEntryWidget.h @@ -0,0 +1,35 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Interfaces/OnlineSessionInterface.h" +#include "Blueprint/UserWidget.h" +#include "MySessionListEntryWidget.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API UMySessionListEntryWidget : public UUserWidget +{ + GENERATED_BODY() + +public: + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget)) + class UTextBlock* IndexText; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget)) + class UTextBlock* SessionNameText; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget)) + class UTextBlock* PlayersCountText; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(BindWidget)) + class UTextBlock* PingText; + + void Update(int SessionIndex, const FOnlineSessionSearchResult& Session); + + int SessionId; + FString SessionName; +}; diff --git a/Source/TurnBasedTutorial/MySessionListWidget.cpp b/Source/TurnBasedTutorial/MySessionListWidget.cpp new file mode 100644 index 0000000..4c69dc5 --- /dev/null +++ b/Source/TurnBasedTutorial/MySessionListWidget.cpp @@ -0,0 +1,81 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "MySessionListWidget.h" + +#include "MyGameInstanceSubsystem.h" +#include "Components/VerticalBox.h" +#include "MySessionListEntryWidget.h" +#include "Components/Button.h" +#include "Kismet/GameplayStatics.h" + +void UMySessionListWidget::NativeConstruct() +{ + Super::NativeConstruct(); + + RefreshListButton->OnClicked.AddDynamic(this, &ThisClass::OnRefreshListButtonClicked); + ConnectToSelectedSessionButton->OnClicked.AddDynamic(this, &ThisClass::ConnectToFirstSession); + + const auto MyGameInstanceSubsystem = GetMyGameSubsystem(); + MyGameInstanceSubsystem->OnFindSessionsCompleteEvent.AddUObject(this, &ThisClass::RefreshList); + MyGameInstanceSubsystem->OnJoinSessionCompleteEvent.AddUObject(this, &ThisClass::OnJoinSessionSuccess); + + // Initiate search + MyGameInstanceSubsystem->FindSessions(10, true); +} + +void UMySessionListWidget::RefreshList(const TArray& SessionResults, + bool bSuccessful) +{ + if (!bSuccessful) + { + UE_LOG(LogTemp, Error, TEXT("Find sessions FAILED!!!!")); + // TODO: Mark find sessions error + return; + } + SessionListBox->ClearChildren(); + for (const auto &Session: SessionResults) + { + auto *ItemWidget = CreateWidget(this, EntryClass); + ItemWidget->Update(SessionListBox->GetChildrenCount(), Session); + SessionListBox->AddChild(ItemWidget); + } +} + + +void UMySessionListWidget::OnRefreshListButtonClicked() +{ + // TODO: Show that we started searching... + // Initiate search + SessionListBox->ClearChildren(); + GetMyGameSubsystem()->FindSessions(10, true); +} + +void UMySessionListWidget::ConnectToFirstSession() +{ + GetMyGameSubsystem()->JoinSession(0); +} + + +void UMySessionListWidget::OnJoinSessionSuccess(EOnJoinSessionCompleteResult::Type Result) +{ + if (Result != EOnJoinSessionCompleteResult::Success) + { + UE_LOG(LogTemp, Error, TEXT("Failed to connect to session!!")); + return; + } + if (!GetMyGameSubsystem()->TryConnectToCurrentSession()) + { + UE_LOG(LogTemp, Error, TEXT("Failed to travel client to session!!")); + return; + } + UE_LOG(LogTemp, Display, TEXT("Connected and travelled to session!!!")); +} + + +UMyGameInstanceSubsystem* UMySessionListWidget::GetMyGameSubsystem() const +{ + const UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(GetWorld()); + UMyGameInstanceSubsystem* GameInstanceSubsystem = GameInstance->GetSubsystem(); + return GameInstanceSubsystem; +} diff --git a/Source/TurnBasedTutorial/MySessionListWidget.h b/Source/TurnBasedTutorial/MySessionListWidget.h new file mode 100644 index 0000000..e305a8d --- /dev/null +++ b/Source/TurnBasedTutorial/MySessionListWidget.h @@ -0,0 +1,49 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "MyGameInstanceSubsystem.h" + +#include "Blueprint/UserWidget.h" +#include "MySessionListWidget.generated.h" + +/** + * + */ +UCLASS() +class TURNBASEDTUTORIAL_API UMySessionListWidget : public UUserWidget +{ + GENERATED_BODY() + +protected: + virtual void NativeConstruct() override; + + UPROPERTY(meta = (BindWidget)) + class UButton* ConnectToSelectedSessionButton; + + UPROPERTY(meta = (BindWidget)) + class UButton* GoBackToMainMenuButton; + + UPROPERTY(meta = (BindWidget)) + class UButton* RefreshListButton; + + UPROPERTY(meta = (BindWidget)) + class UVerticalBox* SessionListBox; + + UPROPERTY(EditDefaultsOnly, Category="Session Info Class") + TSubclassOf EntryClass; + + void RefreshList(const TArray& SessionResults, bool bSuccessful); + + void OnJoinSessionSuccess(EOnJoinSessionCompleteResult::Type Result); + +private: + UMyGameInstanceSubsystem* GetMyGameSubsystem() const; + + UFUNCTION() + void OnRefreshListButtonClicked(); + + UFUNCTION() + void ConnectToFirstSession(); +};