Skip to main content

Put it all together - Joinable sessions with peer-to-peer - (Unreal Engine module)

Last updated on October 24, 2024

Connect Create Match Session menu to the create, leave, and display current session status

  1. Begin by opening the CreateMatchSessionP2PWidget_Starter CPP file and navigate to the CreateSession function. Add a call to the create session function from the Online Session. Remember that the parent widget stores what game mode the player has selected, hence, we retrieve that selected game mode and pass it to the Online Session.

    void UCreateMatchSessionP2PWidget_Starter::CreateSession() const
    {
    if (OnlineSession->ValidateToStartSession.IsBound() &&
    !OnlineSession->ValidateToStartSession.Execute())
    {
    return;
    }

    // Make sure the retry and cancel game session is performed by this class when the P2P network type is selected.
    W_Parent->GetProcessingWidgetComponent()->OnCancelClicked.Clear();
    W_Parent->GetProcessingWidgetComponent()->OnRetryClicked.Clear();
    W_Parent->GetProcessingWidgetComponent()->OnCancelClicked.AddUObject(this, &ThisClass::CancelJoiningSession);
    W_Parent->GetProcessingWidgetComponent()->OnRetryClicked.AddUObject(this, &ThisClass::CreateSession);

    W_Parent->SetLoadingMessage(TEXT_REQUESTING_SESSION_CREATION, false);
    W_Parent->SwitchContent(UCreateMatchSessionWidget::EContentType::LOADING);

    OnlineSession->CreateMatchSession(
    OnlineSession->GetLocalUserNumFromPlayerController(GetOwningPlayer()),
    EGameModeNetworkType::P2P,
    W_Parent->GetSelectedGameModeType());
    }
  2. Navigate to CancelJoiningSession function. Here, we simply call LeaveSession to cancel joining. Since we are in a peer-to-peer (P2P) session, there is a chance that, upon joining, the session info already includes the host IP address. In that case, the UI won't let the player cancel the session. Otherwise, the game will wait to receive updates from the backend, and the game will let the player cancel.

    void UCreateMatchSessionP2PWidget_Starter::CancelJoiningSession() const
    {
    W_Parent->SetLoadingMessage(TEXT_LEAVING_SESSION, false);
    W_Parent->SwitchContent(UCreateMatchSessionWidget::EContentType::LOADING);

    OnlineSession->LeaveSession(
    OnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession));
    }
  3. You have prepared several callback functions previously. Those need to be bound to the delegate in order for them to work. Still in the CPP file, navigate to NativeOnActivated and replace it with the code below:

    void UCreateMatchSessionP2PWidget_Starter::NativeOnActivated()
    {
    Super::NativeOnActivated();

    // Get online session
    UOnlineSession* BaseOnlineSession = GetWorld()->GetGameInstance()->GetOnlineSession();
    if (!ensure(BaseOnlineSession))
    {
    return;
    }
    OnlineSession = Cast<UAccelByteWarsOnlineSessionBase>(BaseOnlineSession);
    ensure(OnlineSession);

    // Get parent menu widget
    W_Parent = GetFirstOccurenceOuter<UCreateMatchSessionWidget>();
    if (!ensure(W_Parent))
    {
    return;
    }

    OnlineSession->GetOnCreateSessionCompleteDelegates()->AddUObject(this, &ThisClass::OnCreateSessionComplete);
    OnlineSession->GetOnLeaveSessionCompleteDelegates()->AddUObject(this, &ThisClass::OnCancelJoiningSessionComplete);
    OnlineSession->GetOnSessionServerUpdateReceivedDelegates()->AddUObject(this, &ThisClass::OnSessionServerUpdateReceived);

    Btn_StartMatchSessionP2P->OnClicked().AddUObject(this, &ThisClass::CreateSession);
    }
  4. You also need to properly unbind them when they're not needed. To do so, navigate to NativeOnDeactivated and replace it with the code below:

    void UCreateMatchSessionP2PWidget_Starter::NativeOnDeactivated()
    {
    Super::NativeOnDeactivated();

    OnlineSession->GetOnCreateSessionCompleteDelegates()->RemoveAll(this);
    OnlineSession->GetOnLeaveSessionCompleteDelegates()->RemoveAll(this);
    OnlineSession->GetOnSessionServerUpdateReceivedDelegates()->RemoveAll(this);

    Btn_StartMatchSessionP2P->OnClicked().RemoveAll(this);
    W_Parent->GetProcessingWidgetComponent()->OnRetryClicked.RemoveAll(this);
    W_Parent->GetProcessingWidgetComponent()->OnCancelClicked.RemoveAll(this);
    }

Connect Browse Match menu to the find, join, and display current session status

  1. Open the BrowseMatchP2PWidget_Starter CPP file and navigate to FindSessions function. Here, you need to call the FindSessions function from Online Session. Note that, if you want to increase the number of maximum sessions that the backend will return, you can increase the SessionsNumToQuery value in the Header file.

    void UBrowseMatchP2PWidget_Starter::FindSessions(const bool bForce) const
    {
    W_Parent->SetLoadingMessage(TEXT_LOADING_DATA, true, false);
    W_Parent->SwitchContent(UBrowseMatchWidget::EContentType::BROWSE_LOADING);
    Btn_Refresh->SetIsEnabled(false);

    OnlineSession->FindSessions(
    OnlineSession->GetLocalUserNumFromPlayerController(GetOwningPlayer()),
    SessionsNumToQuery,
    bForce);
    }
  2. Navigate to the CancelJoining function and replace it with the code below. Just like in the Create Match menu, this function will simply call LeaveSession.

    void UBrowseMatchP2PWidget_Starter::CancelJoining() const
    {
    W_Parent->SetLoadingMessage(TEXT_LEAVING_SESSION, false, false);
    W_Parent->SwitchContent(UBrowseMatchWidget::EContentType::JOIN_LOADING);

    OnlineSession->LeaveSession(
    OnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession));
    }
  3. Navigate to the JoinSession function and replace it with the code below to call the corresponding Online Session function:

    void UBrowseMatchP2PWidget_Starter::JoinSession(const FOnlineSessionSearchResult& SessionSearchResult) const
    {
    if (OnlineSession->ValidateToJoinSession.IsBound() &&
    !OnlineSession->ValidateToJoinSession.Execute(SessionSearchResult))
    {
    return;
    }

    W_Parent->SetLoadingMessage(TEXT_JOINING_SESSION, false, false);
    W_Parent->SwitchContent(UBrowseMatchWidget::EContentType::JOIN_LOADING);

    OnlineSession->JoinSession(
    OnlineSession->GetLocalUserNumFromPlayerController(GetOwningPlayer()),
    OnlineSession->GetPredefinedSessionNameFromType(EAccelByteV2SessionType::GameSession),
    SessionSearchResult);
    }
  4. Bind the callback functions to the callback delegates. Still in the CPP file, navigate to NativeOnActivated and replace it with the code below:

    void UBrowseMatchP2PWidget_Starter::NativeOnActivated()
    {
    Super::NativeOnActivated();

    // Get online session
    UOnlineSession* BaseOnlineSession = GetWorld()->GetGameInstance()->GetOnlineSession();
    if (!ensure(BaseOnlineSession))
    {
    return;
    }
    OnlineSession = Cast<UAccelByteWarsOnlineSessionBase>(BaseOnlineSession);
    ensure(OnlineSession);

    // Get parent menu widget
    W_Parent = GetFirstOccurenceOuter<UBrowseMatchWidget>();
    if (!ensure(W_Parent))
    {
    return;
    }

    OnlineSession->GetOnLeaveSessionCompleteDelegates()->AddUObject(this, &ThisClass::OnCancelJoiningComplete);
    OnlineSession->GetOnFindSessionsCompleteDelegates()->AddUObject(this, &ThisClass::OnFindSessionComplete);
    OnlineSession->GetOnJoinSessionCompleteDelegates()->AddUObject(this, &ThisClass::OnJoinSessionComplete);
    OnlineSession->GetOnSessionServerUpdateReceivedDelegates()->AddUObject(this, &ThisClass::OnSessionServerUpdateReceived);

    Btn_Refresh->OnClicked().AddUObject(this, &ThisClass::FindSessions, true);
    W_Parent->GetJoiningWidgetComponent()->OnCancelClicked.AddUObject(this, &ThisClass::CancelJoining);

    FindSessions(false);
    }
  5. Implement a way to properly unbind those callbacks. Navigate to NativeOnDeactivated and replace it with the code below:

    void UBrowseMatchP2PWidget_Starter::NativeOnDeactivated()
    {
    Super::NativeOnDeactivated();

    OnlineSession->GetOnLeaveSessionCompleteDelegates()->RemoveAll(this);
    OnlineSession->GetOnFindSessionsCompleteDelegates()->RemoveAll(this);
    OnlineSession->GetOnJoinSessionCompleteDelegates()->RemoveAll(this);
    OnlineSession->GetOnSessionServerUpdateReceivedDelegates()->RemoveAll(this);

    Btn_Refresh->OnClicked().RemoveAll(this);
    W_Parent->GetJoiningWidgetComponent()->OnCancelClicked.RemoveAll(this);
    }
  6. Compile your project and make sure there are no errors.

Resources