4.2. PiaInet 応用機能

ブロックリスト

ゲームサーバーにログイン後、特定のユーザーからのハラスメント対策として NEX で提供されているブロックリストを利用できます。ブロックリストは以下の機能を提供します。

  • ブロックリストに登録したユーザーが、自分が参加しているマッチメイクセッションに参加するのをブロックする
  • ブロックリストに登録したユーザーが参加しているマッチメイクセッションに、自分が参加してしまうのをブロックする
  • ブロックリストに登録したユーザーが、自分の状態を取得できないようにする(プライバシーフィルタ機能)

ブロックリストはゲームサーバー毎(したがってアプリケーション毎)に1ユーザーにつき 100 人登録可能です。 100 人以上登録しようとした場合、先に登録したものから順番にブロックリストから削除されていきます(先入れ先出し方式)。 そのため、ブロックリストの管理をアプリケーション内で行うかどうかは、アプリケーション毎に決めることができます。

nn::pia::session::BrowseSessionAsync() に nn::pia::inet::NexSessionSearchCriteriaParticipant を指定して検索する場合、検索対象となるユーザーが自分をブロックリストに登録している場合は検索結果に含まれません。ただし、そのセッションの他の参加者が自分をブロックリストに登録しているかどうかについては関知しません。

また、nn::pia::inet::NexSessionSearchCriteria を指定して検索する場合、ブロックリストに登録した/されたユーザーが参加しているかどうかのチェックを行いません。そのため、実際にセッションに参加しようとするまでブロックリストに登録した/されたユーザーが参加していることはわかりません。プライバシーフィルタ機能はあくまで特定のユーザーに対する付きまといを防止するものであることに留意してください。

ブロックリスト管理は以下の API で行います。いずれの API も非同期処理になり、ディスパッチ関数で処理を進めつつ、処理の完了を待ちます。

  • ブロックリストへの追加は nn::pia::inet::NexFacade::AddToBlockListAsync()
  • ブロックリストからの削除は nn::pia::inet::NexFacade::RemoveFromBlockListAsync()
  • ブロックリストのクリアは nn::pia::inet::NexFacade::ClearBlockListAsync()
  • ブロックリストの取得は nn::pia::inet::NexFacade::RequestBlockListAsync() 

 

nn::pia::PrincipalId principalIdArray[nn::pia::inet::PrincipalIdArraySizeMax];
uint32_t principalIdSize;

// ブロックリストに登録するユーザーのプリンシパル ID を配列に入れる
GetTargetPrincipalIds(principalIdArray, &principalIdSize);

// ブロックリストに登録
nn::pia::Result result = nn::pia::inet::NexFacade::GetInstance()->AddToBlockListAsync(principalIdArray, principalIdSize);
if (result.IsFailure())
{
    // エラーハンドリング
}

while (nn::pia::inet::NexFacade::GetInstance()->IsAddToBlockListCompleted() == false)
{
    // 非同期処理を進めるために NEX と Pia のディスパッチ関数を呼び出します
    nn::nex::Scheduler::GetInstance()->DispatchAll();
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
}

result = nn::pia::inet::NexFacade::GetInstance()->GetAddToBlockListResult();
if (result.IsFailure())
{
    // エラーハンドリング
}
nn::pia::PrincipalId principalIdArray[nn::pia::inet::PrincipalIdArraySizeMax];
uint32_t principalIdSize;

// ブロックリストの登録ユーザーを取得する
nn::pia::Result result = nn::pia::inet::NexFacade::GetInstance()->RequestBlockListAsync();
if (result.IsFailure())
{
    // エラーハンドリング
}

while (nn::pia::inet::NexFacade::GetInstance()->IsRequestBlockListCompleted() == false)
{
    // 非同期処理を進めるために NEX と Pia のディスパッチ関数を呼び出します
    nn::nex::Scheduler::GetInstance()->DispatchAll();
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
}

result = nn::pia::inet::NexFacade::GetInstance()->GetRequestBlockListResult();
if (result.IsFailure())
{
    // エラーハンドリング
}

result = nn::pia::inet::NexFacade::GetInstance()->GetBlockList(principalIdArray, nn::pia:inet::PrincipalIdArraySizeMax, &principalIdSize);
if (result.IsFailure())
{
    // エラーハンドリング
}

// principalIdArray にコピーされたユーザーのプリンシパル ID をプリント(コピーされた数は principalIdSize に格納されている)
for (uint32_t i = 0; i < principalIdSize; ++i)
{
    PIA_SAMPLE_PRINT("BlockListNo.%d: %lld\n", i, principalIdArray[i]);
}

 

アプリケーション定義のイベント通知

注意:

この機能は NEX 4.0.0 以降、非推奨となっています。該当するバージョンの NEX を Pia と組み合わせて使用する場合、フレンドプレゼンスなど他の通知機能の使用を検討してください。

イベントの通知

ゲームサーバーにログイン後、同じゲームサーバーにログインしているフレンドに対して、アプリケーションで定義したイベントを通知できます。イベント通知処理はゲームサーバーにログインし、NexFacade::Bind() の呼び出し後に行えます。

この機能は、ユーザーが通信相手にイベントを送信するような実装を想定してサーバー側も含めて設計されていますので、 それを越えるような頻度の送信を行ってはいけません。具体的には、次のような制限になります。

  • ユーザーがイベントを送信する、ということ以外のデータ送信に使用してはいけません。例えば、本来 P2P で送受信されるべきである対戦中のデータのやりとりなどです。
  • ユーザーの連続操作による過度の送信を防ぐために、1 分間に 10 回の頻度を越えないように制限する必要があります。
  • ゲーム定義のイベントタイプは nn::nex::NotificationEvents::GameNotificationEvent 1~8 が使用できます。

イベント通知処理は非同期処理です。NexFacade::UpdateNotificationDataAsync() を呼び出すことで非同期処理が開始され、NexFacade::IsUpdateNotificationDataCompleted() によって非同期処理の終了を検知できます。ゲームサーバーへのイベント送信に成功すると NexFacade::GetUpdateNotificationDataResult() は IsSuccess() が真となる Result 値を返します。

コード 4-4. アプリケーション定義のイベント通知
/*
ゲームサーバーへのログイン、NexFacade::Bind() の呼び出しを済ませておきます。
*/


// 通知イベントのパラメータ設定
uint32_t param1 = static_cast<uint32_t>(nn::pia::inet::NexFacade::GetInstance()->GetLocalPrincipalId() >> 32);
uint32_t param2 = static_cast<uint32_t>(nn::pia::inet::NexFacade::GetInstance()->GetLocalPrincipalId() & 0x00000000ffffffff);
nn::nex::NotificationEvents::NotificationEvents eventType =nn::nex::NotificationEvents::GameNotificationType1;
nn::pia::common::String stringParam(SAMPLE_STRING("Test"));

// 通知イベントの送信
nn::pia::Result result = nn::pia::inet::NexFacade::GetInstance()->UpdateNotificationDataAsync(eventType, param1, param2, stringParam);
if (result.IsFailure())
{
    // エラー処理
}

// 非同期処理の開始に成功した場合、ディスパッチ関数を定期的に呼び出して非同期処理の進行を待つ必要があります
while (nn::pia::inet::NexFacade::GetInstance()->IsUpdateNotificationDataCompleted() == false)
{
    // Pia と NEX の Scheduler::Dispatch を呼ぶ必要があります
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
    nn::nex::Scheduler::GetInstance()->DispatchAll();
}

result = nn::pia::inet::NexFacade::GetInstance()->GetUpdateNotificationDataResult();
if (result.IsFailure())
{
    // エラー処理
}

通知イベントの受信

フレンドからゲームサーバーに送信されたイベントを受信するには、アプリケーション側で nn::nex::NotificationEventHandler を継承するクラスを宣言します。そして、そのインスタンスのポインタをゲームサーバーにログインする際に使用した nn::nex::NgsFacade クラスのインスタンスに nn::nex::NgsFacade::RegisterNotificationEventHandler() で登録します。イベントハンドラでの通知イベントのハンドリング方法については、NEX プログラミングマニュアルの [サーバーサービス] - [マッチメイク] - [通知イベントをハンドリングする] の説明を参照してください。

イベントハンドラを登録するよりも前にゲームサーバーに送信されたイベントはイベントハンドラに通知されません。登録前に送信されたイベントを受信するに は、nn::pia::inet::NexFacade::RetrieveNotificationDataAsync() を使用して受信します。イベント受信処理は非同期処理です。 NexFacade::RetrieveNotificationDataAsync() を呼び出すことで非同期処理が開始され、NexFacade::IsRetrieveNotificationDataCompleted() によって非同期処理の終了を検知できます。ゲームサーバーへのイベント送信に成功すると NexFacade::GetRetrieveNotificationDataResult() は IsSuccess() が真となる Result 値を返します。

コード 4-5. 通知イベントの受信
// イベントハンドラクラスの宣言
class SampleNexNofiticationEventHandler : public nn::nex::NotificationEventHandler
{
public:
    SampleNexNofiticationEventHandler()
    {
    }
    virtual ~SampleNexNofiticationEventHandler()
    {
    }

    virtual void ProcessNotificationEvent(const nn::nex::NotificationEvent& oEvent)
    {
        PIA_SAMPLE_PRINT("Received notification event. Type:%u, Param1:%lld, Param2:%lld\n",
                       oEvent.GetType(),
                       static_cast<uint64_t>(oEvent.GetParam1()),
                       static_cast<uint64_t>(oEvent.GetParam2()));
    }
};

// イベントハンドラのインスタンス
SampleNexNofiticationEventHandler s_NexNotificationHandler;

/*
ゲームサーバーへのログインを済ませておきます。
*/


// ゲームサーバーからのイベント通知を受信するイベントハンドラを登録(登録したイベントハンドラはログアウト時に削除します)
nns::pia::Nex_GetNgsFacadeInstance()->RegisterNotificationEventHandler(&s_NexNotificationHandler);

// NexFacade に NEX ゲームサーバ情報を設定
nn::pia::inet::NexFacade::LoginInfo loginInfo;

// ゲームサーバーID
loginInfo.gameServerId = LoginGameId;
// アクセスキー
nn::pia::common::String accessKey(LoginAccessKey);
loginInfo.pAccessKey = &accessKey;
// ログイン時に使用した NgsFacade のポインタ
loginInfo.pNgsFacade = nns::pia::Nex_GetNgsFacadeInstance();

nn::pia::inet::NexFacade::GetInstance()->Bind(&loginInfo);
 
// 既にゲームサーバーに通知済みのイベントを取得(ここでは GameNotificationType1 から GameNotificationType4 までのイベントタイプを設定)
nn::nex::qList<nn::nex::NotificationEvent> listNotificationEvent;
 
result = nn::pia::inet::NexFacade::GetInstance()->RetrieveNotificationDataAsync(0xf, &listNotificationEvent);
{
    // エラー処理
}
 
// 非同期処理の開始に成功した場合、ディスパッチ関数を定期的に呼び出して非同期処理の進行を待つ必要があります
while (nn::pia::inet::NexFacade::GetInstance()->IsRetrieveNotificationDataCompleted() == false)
{
    // Pia と NEX の Scheduler::Dispatch を呼ぶ必要があります
    nn::pia::common::Scheduler::GetInstance()->Dispatch();
    nn::nex::Scheduler::GetInstance()->DispatchAll();
}
 
result = nn::pia::inet::NexFacade::GetInstance()->GetRetrieveNotificationDataResult();
if (result.IsFailure())
{
    // エラー処理
}
 
// 取得したイベントを処理
for (nn::nex::qList<nn::nex::NotificationEvent>::const_iterator it = listNotificationEvent.begin(); it != listNotificationEvent.end(); ++it)
{
    PIA_SAMPLE_PRINT("Got friend notification event. Type:%u, Param1:%lld, Param2:%lld\n",
        it->GetType(),
        static_cast<uint64_t>(it->GetParam1()),
        static_cast<uint64_t>(it->GetParam2()));
}