7.11. 応用機能 - フレンド合流マッチメイク

フレンド合流マッチメイクについて説明します。

参考:

フレンド合流マッチメイクはインターネットマッチメイクのみ対応しています。

注意:

Pia 5.2.11 以降、nn::pia::inet::SessionType_Friend は廃止となります。Pia 5.2.10 以前の Pia 5.x においては非推奨です。

概要

フレンドの参加しているセッションに合流する方法について説明します。フレンドプレゼンス機能を使用する方法とフレンドが参加しているセッションを検索する方法があります。

フレンドプレゼンス機能を使用すると、自分の参加しているセッションの情報やそのセッションに合流可能かどうかをフレンドと共有できます。フレンドから共有されたセッションの情報を PiaSession に指定して、セッションに参加できます。フレンドプレゼンス機能を使用するフレンド合流は「同じゲームをプレイ中のフレンドのセッションに合流」と「HOME メニューのフレンドリストからフレンドのセッションに合流」の2つの方法があります。

フ レンドプレゼンスライブラリの詳細については、CTR プログラミングマニュアルの「プレゼンス機能」を参照してください。 合流機能の詳細については、NEX プログラミングマニュアルの「マッチメイク - フレンドプレゼンスライブラリを使用した合流」を参照してください。

フレンド合流用セッションの構築

通常のセッションと同様に合流用のセッションを構築します。その際、フレンド以外が参加しないように以下に挙げる項目のうちいずれか一つ以上について対応することを推奨します。

  • フレンド合流用と通常用でゲームモードの値を分ける
  • セッションユーザーパスワードを設定する
  • あいことばを設定する

フレンド合流用セッションへの参加

フレンド合流用セッションへの参加はフレンドプレゼンス機能を使用する方法とフレンドが参加しているセッションを検索する方法があります。

フレンドプレゼンス機能を使用したセッション合流

フレンドプレゼンス機能を使用したセッション合流は、自分自身やフレンドのプレゼンスをゲームの進行状況に応じて更新することで、合流に必要な情報を適宜共有しておき、合流する側がプレゼンスの内容を確認してセッションへの合流を行います。

プレゼンスで共有するゲームモードに合流先のセッション ID や合流可能かどうかのフラグが含まれます。合流時は合流可能であることを確認してから合流します。ただし、合流可能と判断できたとしてもプレゼンスがリアルタイムに正しい状態を示しているとは限らないため、合流できない場合があります。

プレゼンスの共有

フレンドプレゼンスライブラリのプレゼンス機能を使用してゲームモードを共有できます。ゲームモードには合流に必要なセッション ID などのセッション情報や合流可能フラグが含まれています。

自分自身がセッションに参加し、フレンドからの合流を待つ場合、自分自身のプレゼンスを更新して参加中のセッション ID や合流可能かどうかをフレンドと共有します。セッションから離脱するなどゲームの進行状況に応じて、プレゼンスを更新します。

コード 7-20. プレゼンスの更新
// プレゼンスで共有するゲームモード
nn::friends::GameMode gameMode;
 
// フレンドプレゼンスと連動させるため、ゲームモードは 0-63 の範囲に設定します
gameMode.joinGameMode = FriedsGameMode;
// グループ ID にセッション ID を設定します
gameMode.joinGroupId = nn::pia::session::Session::GetInstance()->GetSessionId();
// NEX から渡されたセッションホストのプリンシパル ID を取得するためにホストのステーションインスタンスを取得します
nn::pia::StationId hostStationId = nn::pia::session::Session::GetInstance()->GetHostStationId();
nn::pia::transport::Station* pHostStation = nn::pia::transport::StationManager::GetInstance()->GetStation(hostStationId);
// セッションホストのプリンシパル ID を取得し、設定します
pHostStation->GetPrincipalId(&gameMode.ownerPrincipalId);
// セッションに合流可能かどうかのフラグを設定します
gameMode.joinAvailabilityFlag = nn::friends::JOIN_AVAILABILITY_JOINABLE;

// プレゼンスで共有する文字列
const wchar_t* DESCRIPTION = L"Available now";
 
// プレゼンスを更新
nn::Result result = nn::friends::UpdateGameMode(gameMode, DESCRIPTION);
if (result.IsFailure())
{
    uint32_t errorCode = nn::friends::ResultToErrorCode(result);
    // エラーハンドリング
}

同じゲームをプレイ中のフレンドのプレゼンス取得

フレンドが参加しているセッションに合流する場合、フレンドのプレゼンスから合流に必要な情報を取得します。

フレンドが通信プレイしている場合、同じ合流ゲーム ID のゲーム起動中にフレンドプレゼンスで合流先セッションの情報を取得できます。

合流ゲーム ID の設定の詳細については NEX プログラミングマニュアル「マッチメイク - フレンドプレゼンスライブラリを使用した合流 - 実装」の項を参照してください。

コード 7-21. 同じ合流ゲーム ID のゲーム起動中のプレゼンス取得
size_t friendsNum = 0;
nn::friends::FriendKey friendIdList[FRIENDS_LIST_MAX];
nn::friends::FriendPresence friendPresenceList[FRIENDS_LIST_MAX];


// フレンドプレゼンスのリストを取得します
nn::friends::GetFriendKeyList(friendIdList, &friendsNum, 0, FRIENDS_LIST_MAX);
nn::friends::GetFriendPresence(friendPresenceList, friendIdList, friendsNum);


// 取得したプレゼンスが合流可能状態かどうかチェックします
for (size_t i = 0; i < friendsNum; i++)
{
    if (friendPresenceList[i].isOnline && friendPresenceList[i].IsJoinable(FriedsGameModeMask))
    {
        // 合流可能
    }
}

フレンドリストから合流する場合のフレンドのプレゼンス取得

HOME メニューのフレンドリストでフレンドのプレイ中のゲームに合流可能な場合に、フレンドリストからフレンドが遊んでいるゲームを起動できます。

フレンドリストからゲームを起動された場合、フレンドリストから起動されたこと、および選択されたフレンドを起動時に取得できます。フレンドリストから起動されたことを検出したら、選択されたフレンドのプレゼンスを取得し、フレンドのセッションに合流できます。

コード 7-22. フレンドリストからゲームを起動した場合のプレゼンス取得
// フレンドリストからの起動であるかどうかを判定
isFromFriendList = false;
nn::friends::FriendKey friendIdForJoinIn;
nn::friends::FrinedPresence friendPresenceForJoinIn;
 
if (nn::friends::IsFromFriendList(&friendIdForJoinIn))
{
    // フレンドリストから起動された
    isFromFriendList = true;
    // フレンドプレゼンスを取得
    nn::friends::GetFriendPresence(&friendPresenceForJoinIn, &friendIdForJoinIn);
    // 取得したプレゼンスが合流可能状態かどうかチェックします
    if (friendPresenceForJoinIn.isOnline && friendPresenceForJoinIn.IsJoinable(FriedsGameModeMask))
    {
        // 合流可能
    }
}

プレゼンスを使用したセッション合流

取得したプレゼンスのゲームモードから合流可能と判断できた場合、ゲームモードの合流先セッション ID の値を nn::pia::inet::NexJoinSessionSetting に指定し、nn::pia::session::Session::JoinSessionAsync() でセッションに合流できます。

コード 7-23. プレゼンスを使用したセッション合流
// セッション参加処理用の設定
nn::pia::inet::NexJoinSessionSetting joinSessionSetting;
 
// 合流可能と判定できたプレゼンスのゲームモードの合流先セッション ID を、セッション参加処理用の設定にコピー
joinSessionSetting.SetSessionId(friendPresence.gameMode.joinGroupId);
// セッション参加処理の非同期処理を開始
result = nn::pia::session::Session::GetInstance()->JoinSessionAsync(&joinSessionSetting);
if (result.IsFailure())
{
    // エラー処理
}


// 非同期処理の開始に成功した場合、ディスパッチ関数を定期的に呼び出して非同期処理の進行を待つ必要があります
while (nn::pia::session::Session::GetInstance()->IsJoinSessionCompleted() == false)
{
    nn::nex::Scheduler::GetInstance()->DispatchAll();
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
}
 
// 非同期処理の結果確認
result = nn::pia::session::Session::GetInstance()->GetJoinSessionResult();
if (result.IsFailure())
{
    // エラー処理
}

/* 非同期処理に成功していれば、フレンドのセッションへの合流に成功し、他のステーションと通信可能な状態になっています */

フレンドが参加中のセッションの検索によるセッション合流

nn::pia::inet:NexSessionSearchCriteriaByParticipant にフレンドのプリンシパル ID を検索条件として指定し、nn::pia::session::Session::BrowseSessionAsync() を呼び出すことでフレンドが参加しているセッションを検索できます。検索結果として得られるセッション情報の募集状態、参加人数の空き状態を確認し、合流可能であれば nn::pia::inet::NexJoinSessionSetting にセッション ID を指定し、nn::pia::session::JoinSessionAsync() で合流先のセッションに参加します。

セッション検索を行う前に、検索条件として指定するフレンドのプレゼンスがオンラインプレイ中になっていることの確認を推奨します。

コード 7-24. フレンドが参加中のセッションへの合流
size_t friendsNum = 0;
nn::friends::FriendKey friendIdList[FRIENDS_LIST_MAX];


// フレンドリストを取得します
nn::Result sdkResult = nn::friends::GetFriendKeyList(friendIdList, &friendsNum, 0, FRIENDS_LIST_MAX);
if (sdkResult.IsFailure())
{
    // エラー処理
}

// フレンドの情報からのプリンシパル ID を取得する
nn::pia::PrincipaldId onlineFriendsList[MaxFriendSessionNum];
for (int i = 0; i < friendsNum; ++i)
{
    onlineFriendsList[i] = friendIdList[i].principalId;
}

// フレンドのプリンシパル ID を検索条件としてセットする
nn::pia::inet::NexSessionSearchCriteriaParticipant searchCriteria;
searchCriteria.SetParticipantPrincipalId(onlineFriendsList, friendsNum);

nn::pia::Result result = nn::pia::session::Session::GetInstance()::BrowseSessionAsync(&searchCriteria);
if (result.IsFailure())
{
    // エラー処理
}

// 検索結果から合流先を選択する
nn::pia::session::ISessionInfo* pTargetSessionInfo = NULL;
nn::pia::session::ISessionInfoList::Iterator it = nn::pia::session::Session::GetInstance()->GetBrowsedSessionInfoList()->Begin();
uint8_t foundSessionNum = nn::pia::session::Session::GetInstance()->GetBrowsedSessionInfoList()->GetSize();
for (uint8_t i = 0; i < foundSessionNum; i++)
{
    if (isTarget())
    {
        pTargetSessionInfo = *it;
    }
    ++it;
}

if (pTargetSessionInfo == NULL)
{
    // エラー処理
}

/*
    セッションに参加可能かどうか、募集状態や空き状態を確認します。
*/


// セッション参加処理用の設定
nn::pia::inet::NexJoinSessionSetting joinSessionSetting;
joinSessionSetting.SetSessionInfoPtr(pTargetSessionInfo);

// セッション参加処理の非同期処理を開始
result = nn::pia::session::Session::GetInstance()->JoinSessionAsync(&joinSessionSetting);
if (result.IsFailure())
{
    // エラー処理
}

// 非同期処理の開始に成功した場合、ディスパッチ関数を定期的に呼び出して非同期処理の進行を待つ必要があります
while (nn::pia::session::Session::GetInstance()->IsJoinSessionCompleted() == false)
{
    nn::nex::Scheduler::GetInstance()->DispatchAll();
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
}
 
// 非同期処理の結果確認
result = nn::pia::session::Session::GetInstance()->GetJoinSessionResult();
if (result.IsFailure())
{
    // エラー処理
}

/* 非同期処理に成功していれば、フレンドのセッションへの合流に成功し、他のステーションと通信可能な状態になっています */