4. Matchmaking

4.1. What Is Matchmaking?

Matchmaking is a multiplayer introduction feature that finds partners on the Internet for a user to play with.

With NEX, a group of users is called a gathering, and a gathering of users that are playing together or cooperating with each other through matchmaking is called a matchmaking session. This concept is independent of a P2P session.

During matchmaking, you can search for and join matchmaking sessions that match conditions specified by the application. For example, you can search for matchmaking sessions created by a friend or search for matchmaking sessions that have attribute values that the application has independently specified. You can also search for matchmaking sessions by specifying a partner.

Depending on the application, a single user can create and join multiple matchmaking sessions. For example, you could use one matchmaking session to manage P2P communications, another matchmaking session to manage teams, and yet another matchmaking session for messaging between friends. For more information about using matchmaking sessions to manage teams, see 4.10 Joining Multiple Users at the Same Time to a Matchmaking Session.

With NEX, the owner of the matchmaking session is called the owner, and the representative terminal that is receiving participation from other terminals with P2P communication is called the host.

To group users on a broader basis than a single matchmaking session, use a persistent gathering (4.18). With matchmaking sessions, users automatically leave the session when they log out from the server. With persistent gatherings, however, you can keep users grouped in the gathering even if they log out.

Matchmaking includes support for PUSH event notifications through the game server, instant messaging, and a feature for impartially recording match results.

4.2. Overall Matchmaking Flow

The following steps show the overall flow of the matchmaking process.

  1. Log in to the game server.
  2. Initialize a service client (4.3. Initializing/Finalizing a Service Client).
  3. Register a matchmaking session. Alternatively, search for a matchmaking session to join (Sections 4.4, 4.5, and 4.6).
  4. Establish mutual connections between the participants of the matchmaking session (Chapter 8 Peer-to-Peer Communication).
  5. Leave the matchmaking session. Delete the session if it is unnecessary (Sections 4.7 and 4.15.7).
  6. Finalize the service client, and log out from the game server. Alternatively, return to step 3.

4.3. Initializing and Finalizing a Service Client

NEX communicates with game servers through service client APIs that support the services provided by the game servers, such as matchmaking, rankings, and instant messaging. To initialize each of the service clients, you must set a pointer to a valid Credential object in the ServiceClient::Bind function. The following three classes derived from ServiceClient are the service clients used for matchmaking.

  • MatchmakeExtensionClient: Registers, searches for, joins, and handles other similar operations for matchmaking sessions.
  • NATTraversalClient: Performs NAT traversal. This class is automatically used within the library except during initialization and shutdown.
  • MessagingClient: Sends and receives instant messages. This class is not needed if instant messaging is not used.

Use the NgsFacade::GetCredentials function to get the Credentials object after you log in to the game server. Before you log out from the game server, call the ServiceClient::Unbind function to release the Credentials object that was set, and then destroy the ServiceClient object. For more information, see Code 4.1..

Code 4.1. Initializing and Finalizing a Service Client

// Log in to the game server.
LoginGameServer(pNgsFacade);
Credentials* pCredentials = pNgsFacade->GetCredentials();

// Create a ServiceClient instance for each login attempt.
MatchmakeExtensionClient* pClient = qNew MatchmakeExtensionClient();
pClient->Bind(pCredentials);

// Do the processing.
pClient->DoSomething();

// Unbind and destroy the object before logging out.
pClient->Unbind();
qDelete pClient;

// Log out.
LogoutGameServer(pNgsFacade);

4.4. Registering a Matchmaking Session

Use the MatchmakeExtensionClient::CreateMatchmakeSession function to register a matchmaking session on a game server (Code 4.2 Example of Configuring and Registering a Matchmaking Session). The client that calls the CreateMatchmakeSession function automatically joins the matchmaking session as its owner and P2P communication host. The terminal that is not the matchmaking session owner must call the MatchMakingClient::UpdateSessionHost to become the P2P communication host.

This function takes the following arguments: a pointer to a ProtocolCallContext object, a GatheringHolder object that stores a MatchmakeSession object, a pointer to the gathering ID set when asynchronous processing is completed, a pointer to a common key for P2P communication, and up to 256 characters of detailed information such as the name of the client and the character used.

After you have finished registering a matchmaking session, create a P2P session and wait for other participants to join it. For more information, see 8. Peer-to-Peer Communication.

Comments

The destructor for the GatheringHolder class deletes the object that it maintains, just as with std::auto_ptr. For this reason, explicitly call the GatheringHolder::Release function to reuse the MatchmakeSession object stored in a GatheringHolder object.

Code 4.2 Example of Configuring and Registering a Matchmaking Session

static const qUnsignedInt32 s_gameMode = 1;
static const qUnsignedInt16 s_MaxParticipations = 10;

MatchmakeExtensionClient matchmakeClient;

void ExecuteCreateMatchmakeSession()
{
    // Set the conditions for the matchmaking session.
    MatchmakeSession* pMatchmakeSession = qNew MatchmakeSession();
    pMatchmakeSession->SetGameMode(s_gameMode);
    pMatchmakeSession->SetAttribute(1, 3);
    pMatchmakeSession->SetMatchmakeSystemType(MATCHMAKE_SYSTEM_TYPE_ANYBODY);
    pMatchmakeSession->SetMaxParticipants(s_MaxParticipations);
    pMatchmakeSession->SetFlag(GatheringFlags::MigrateOwner);

    qVector<qUnsignedInt8> applicationBuffer;
    applicationBuffer.push_back(1);
    pMatchmakeSession->SetApplicationBuffer(applicationBuffer);
    pMatchmakeSession->SetDescription(_T("Description"));
    pMatchmakeSession->SetOpenParticipation(false);

    // Set the MatchmakeSession in the GatheringHolder.
    GatheringHolder oGatheringHolder = pMatchmakeSession;
    ProtocolCallContext oContext;
    GatheringID gatheringID = INVALID_GATHERINGID;

    // Common key for P2P communication.
    qVector<qByte> sessionKey;

    // Register a matchmaking session with the server, and join a session.
    if (!matchmakeClient.CreateMatchmakeSession(&oContext, oGatheringHolder, &gatheringID, &sessionKey, _T("create matchmake session")))
    {
        // Error processing.
        return;
    }
    // Wait for the asynchronous processing result.
    oContext.Wait();
    if (oContext.GetState()!=CallContext::CallSuccess)
    {
        // Error processing.
    }
}

4.6. Joining a Matchmaking Session

Use the MatchmakeExtensionClient::JoinMatchmakeSession function to join a matchmaking session. This function takes a pointer to a ProtocolCallContext object, the ID of the matchmaking session to join, a pointer to a common key for P2P communication, and detailed client information.

The game server receiving a request verifies the following and continues processing the participant only if there are no problems.

  • The maximum number of matchmaking session participants is not exceeded.
  • The matchmaking session has not been closed to new participants.
  • The other participants in the matchmaking session are not registered to the blacklist of the local system.
  • The local system is not registered to the blacklists of any other participants in the matchmaking session.
  • A friend relationship has been established with the matchmaking session owner if the matchmaking system type is MATCHMAKE_SYSTEM_TYPE_FRIEND.

After you have finished joining a matchmaking session, you must join a P2P session separately to run P2P communication. For more information, see Chapter 8 Peer-to-Peer Communication.

4.7. Leaving a Matchmaking Session

Use the MatchMakingClient::EndParticipation function to leave a matchmaking session. This function takes a pointer to a ProtocolCallContext object, the ID of the matchmaking session to leave, and detailed client information as arguments.

By default, the matchmaking session is deleted when the owner leaves or logs out. When the GatheringFlags::MigrateOwner gathering flag is set, the ownership of the session is not deleted, and is migrated to another participant. The matchmaking session is deleted, however, if there are no other participants.

Warning

If you have joined a P2P session, you must leave both the matchmaking session and the P2P session. For more information, see chapter 8 Peer-to-Peer Communication.

4.8. Using Automatic Matchmaking

When a client uses automatic matchmaking, it joins any matchmaking session that matches the search criteria; or it can register a matchmaking session with those criteria if one does not already exist. You can specify multiple search criteria using a list, and the game server searches by those criteria in order from the start of the list. (The search is halted when a joinable session is found.) A user cannot join the session if either the user is registered on the blacklist of any of the participants, or if any of the participants is registered on the user’s blacklist.

Use the MatchmakeExtensionClient::AutoMatchmake function to perform automatic matchmaking. This function takes the following arguments: a pointer to a ProtocolCallContext object, a MatchmakeSessionSearchCriteria list if multiple search criteria are specified, a GatheringHolder class object that stores a MatchmakeSession object, a pointer to a GatheringHolder class object for storing the asynchronous processing results, and detailed client information. For more information about setting MatchmakeSession conditions, see 4.10. Setting Matchmaking Session Criteria. For more information about MatchmakeSessionSearchCriteria, see 4.11. Setting the Search Criteria and Range.

If there is more than one matchmaking session that meets the search criteria, the game server decides which session to join based on the selection method specified by the MatchmakeSessionSearchCriteria::SetSelectionMethod function. The default is random. The MatchmakeSelectionMethod value can be set using MatchmakeSessionSearchCriteria::SetSelectionMethod. For more information about MatchmakeSelectionMethod, see 4.8.1 Selecting the Matchmaking Session.

When asynchronous processing succeeds, a MatchmakeSession object is set in the GatheringHolder class object to indicate which session was either joined or registered. Although you can get a pointer to a Gathering class object with GatheringHolder::Get, you can cast to a pointer to a MatchmakeSession object. To determine whether a client registered a new matchmaking session or joined an existing matchmaking session, check whether the return value of the Gathering::GetOwnerPID function is the same as the principal ID of the local host.

4.8.1. Selecting the Matchmaking Session

When the auto-matchmaking feature is used, if there is more than one matchmaking session that meets the search criteria, the game server decides which session to join based on the selection method specified by the MatchmakeSessionSearchCriteria::SetSelectionMethod function. The default is random. The MatchmakeSelectionMethod value can be set using MatchmakeSessionSearchCriteria::SetSelectionMethod. If more than 50 matchmaking sessions meet the search criteria, you can apply the selection method specified by the MatchmakeSessionSearchCriteria::SetSelectionMethod function to any 50 of the sessions.

If MATCHMAKE_SELECTION_METHOD_RANDOM is specified, the sessions are selected randomly.

If MATCHMAKE_SELECTION_METHOD_NEAREST_NEIGHBOR is specified, the matchmaking sessions with the closest attribute value to that in the MatchmakeSession object passed as an argument to MatchmakeExtensionClient::AutoMatchmake are selected. The attribute value in the MATCHMAKE_SELECTION_METHOD_NEAREST_NEIGHBOR index is used. If there is more than one matchmaking session with the same attribute value, the matchmaking sessions are selected in order of gathering ID. If more than 50 matchmaking sessions meet the search criteria, the matchmaking sessions with the closest attribute value are not always the ones to be selected.

If MATCHMAKE_SELECTION_METHOD_BROADEN_RANGE is specified, the matchmaking session is selected using the range broadening method. A "range" refers one set of integer values from a sequence of integers divided into multiple levels based on threshold values. The default setting assumes the use of the Elo rating system, where integers from 0 to 10000 are divided into 12 different levels: 0-1100, 1101-1240, 1241-1400, 1401-1520, 1521-1620, 1621-1720, 1721-1815, 1816-1925, 1926-2040, 2041-2180, 2181-2300, 2301-10000. Each level is a range. When using the range broadening method, a matchmaking session that has an attribute value within the same range as the attribute value of the MatchmakeSession object passed as an argument to MatchmakeExtensionClient::AutoMatchmake is randomly selected from the matchmaking sessions that meet the search criteria. The attribute value in the MATCHMAKE_SESSION_BROADEN_RANGE_ATTRIBUTE_INDEX index is used. If a matchmaking session in the same range cannot be found, the scope can be expanded to any range adjacent to the current range. A matchmaking session is then randomly selected from the matchmaking sessions that meet the search criteria in the broader range and have the same attribute value in the MATCHMAKE_SESSION_BROADEN_RANGE_ATTRIBUTE_INDEX index. By default, the range is expanded to the two ranges before and after the current range. For example, based on the ranges given above, if a matchmaking session was not found in the 1401-1520 range, the range would be expanded to 1101-1720. This feature can be used to enable matchmaking with closely ranked players in games that rank players based on a rating score by, for example, setting the attribute value in the MATCHMAKE_SESSION_BROADEN_RANGE_ATTRIBUTE_INDEX index to the rating score and setting the ranges based on the ranks. Also refer to the WebAPI documentation (12.2.2 API Functions for Range Broadening Auto-Matchmaking Feature).

If MATCHMAKE_SELECTION_METHOD_PROGRESS_SCORE is specified, the matchmaking session with the closest game progress score to the value set using MatchmakeSession::SetProgressScore or MatchmakeExtensionClient::UpdateProgressScore is selected from the matchmaking sessions that meet the search criteria. This feature is useful when, for example, a game accepts new participants for the next match after the current match has already begun. It would allow players to join a match that is almost over rather than one that has just begun, reducing the amount of wait time until the next match. To achieve this, you would set the game progress score to 0 at the beginning of the match, and use the MatchmakeExtensionClient::UpdateProgressScore function to periodically update the game progress as the match progresses. Note that frequently calling MatchmakeExtensionClient::UpdateProgressScore increases the load on the server. Update the score at an interval of UPDATE_PROGRESS_SCORE_MINIMUM_INTERVAL_TIME seconds or longer.

If MATCHMAKE_SELECTION_METHOD_BROADEN_RANGE_WITH_PROGRESS_SCORE is specified, the matchmaking session is selected using a combination of range broadening and the game progress score. The matchmaking session that has an attribute value within the same range as the attribute value of the MatchmakeSession object passed as an argument to MatchmakeExtensionClient::AutoMatchmake, and also has the highest game progress score, is selected from the matchmaking sessions that meet the search criteria. The attribute value in the MATCHMAKE_SESSION_BROADEN_RANGE_ATTRIBUTE_INDEX index is used. If a matchmaking session in the same range cannot be found, the scope can be expanded to any range adjacent to the current range. The matchmaking session with the highest game progress score is then selected from the matchmaking sessions that meet the search criteria in the broader range.

If MATCHMAKE_SELECTION_METHOD_SCORE_BASED is specified, the best matchmaking session is selected by applying a score to various parameters. Score conversions are defined in advance. To assign scores for various parameter types, parameters of matchmaking sessions that match the search criteria are compared with the sessions for the user, and the matchmaking session with the highest total score is selected. The following parameters can be used.

  • Rating value difference.
  • Disconnection rate difference.
  • Violation rate difference.
  • Distance, accounting for the Internet path.
  • Country match.
  • Country match without distance information.
  • Matchmaking session duration.
  • Matchmaking session progress.

You can use multiple score conversion settings by switching a settings index. For example, you can change the assignment of scores by changing the setting index according to the game mode. When multiple MatchmakeSessionSearchCriteria objects are specified, the first criterion is used as the strictest score conversion, the second is used somewhat less strictly, and so on to enable the best matchmaking session to be found. To use this feature, you must use an overloaded version of the MatchmakeSessionSearchCriteria::SetSelectionMethod function, which takes a MatchmakeParam argument. The MatchmakeParam object specified to this function must also be specified to the MatchmakeSession using the MatchmakeSession::SetMatchmakeParam function. The application must set the information such as the user's own rating value, disconnect rate, violation rate, and country for the MatchmakeParam function. The MatchmakeExtensionClient::AutoMatchmake function allows you to get the total score from the MatchmakeParam included in the matchmaking session you are participating in. However, if you are the owner of the session, it means no matchmaking occurred, so you cannot get your total score. If the application calculates the rating value, disconnect rate, and violation rate, consider using MatchmakeReferee. Also see the web API documentation (Section 12.2.3 API for Auto-Matchmaking by Scoring Feature).

Code 4.5. Using MATCHMAKE_SELECTION_METHOD_SCORE_BASED

MatchmakeParam param;
param.SetSettingIndex(0);
param.SetRatingValue(1500);

MatchmakeSessionSearchCriteria criteria;
criteria.SetMatchmakeSystemType(MATCHMAKE_SYSTEM_TYPE_ANYBODY);
criteria.SetSelectionMethod(MATCHMAKE_SELECTION_METHOD_SCORE_BASED, param);
qList<MatchmakeSessionSearchCriteria> criteriaList;
criteriaList.push_back(criteria);

MatchmakeSession* matchmakeSession = new MatchmakeSession();
matchmakeSession->SetGameMode(0);
matchmakeSession->SetMatchmakeSystemType(MATCHMAKE_SYSTEM_TYPE_ANYBODY);
matchmakeSession->SetMaxParticipants(4);
matchmakeSession->SetMatchmakeParam(param);
GatheringHolder oGatheringHolder = matchmakeSession;

ProtocolCallContext oContext;
GatheringHolder joinedSession;
matchmakeExtensionClient.AutoMatchmake(&oContext, criteriaList, oGatheringHolder, &joinedSession));

4.8.2. Delaying the Creation of a New Matchmaking Session During Auto-matchmaking

To improve the overall success rate of NAT traversal on P2P networks, auto-matchmaking will delay the creation of a new matchmaking session as much as one second if a matchmaking session that meets the search criteria does not exist when calling from a station with a NAT type of EDM or a high failure rate. The auto-matchmaking feature repeatedly searches for matchmaking sessions during the delay period and does not respond to the client. Delaying the creation of a matchmaking session increases the probability of joining an existing matchmaking session and makes the station less likely to become the host. The default delay time is one second. Contact Nintendo if you want to set a time longer than the default of one second.

The creation of a new session is delayed under the following conditions.

  • It was accessed from a terminal with a NAT type of EDM or with a global IP address that has an aggregate NAT traversal failure rate of 80% or higher.

The results of the NAT type check and NAT traversal success check for each global IP address are recorded on the game server when the terminal logs out or disconnects. This information is shared between all game servers running NEX 3.5 and later versions. The information expires one week from the last report.

You can force a delay by setting MatchmakeFlags::MatchmakeSessionOption0 to MatchmakeFlags::MATCHMAKE_SESSION_OPTION0_FORCE_AUTOMATCH_DELAY using the MatchmakeSession::SetOption0Flag function. If you have set a time longer than the default of one second, be sure to debug your application with this flag enabled.

4.9. Cautions When Determining to Accept Participation in a Peer-to-Peer Session With an Application

When a matchmaking session is opened on the game server, a request to participate in the P2P session associated with the matchmaking session can arrive at any time. In particular, when using the auto matchmaking feature, because joining one of the top 10 matchmaking sessions that can be joined is selected randomly on the game server, the possibility of simultaneously joining the same matchmaking session becomes greater.

For this reason, specify that the application accepts join requests for a short interval, and that the application makes every effort to not reject requests to join a P2P session. (Omit the check for excessive numbers of participants that copes with deadline timing shift issues.)

Rejection at the stage of joining a P2P session is a cause of declining matchmaking success rates.

If a state where joining is not possible lasts for a long time, run the MatchmakeExtensionClient::CloseParticipation and MatchmakeExtensionClient::OpenParticipation functions.

4.10. Joining Multiple Users at Once to a Matchmaking Session

There are cases where users play with friends they know, or play as teams after gathering a group of players. The multiple user group matchmaking session join allows this functionality.

To join multiple users at once, overload the MatchmakeExtensionClient::AutoMatchmake, MatchmakeExtensionClient::CreateMatchmakeSession, and MatchmakeExtensionClient::JoinMatchmakeSession functions by passing the AutoMatchmakeParam, CreateMatchmakeSessionParam, and JoinMatchmakeSessionParam objects as arguments. For example, you can atomically join yourself and other users with known principal IDs by passing the principal IDs to the JoinMatchmakeSessionParam::SetAdditionalParticipant function. The result is all users successfully joining, or an error causing all users to fail joining. Use the JoinMatchmakeSessionParam::SetGatheringIdForParticipationCheck function as an option to check if all users have joined the specified gathering. If you specify JOIN_MATCHMAKE_SESSION_BEHAVIOR_IM_ALREADY_JOINED in the JoinMatchmakeSessionParam::SetJoinMatchmakeSessionBehavior function, you can get other users specified in the JoinMatchmakeSessionParam::SetAdditionalParticipant function joined into the matchmaking session that you have already joined. A NotificationEvents::AddedToGathering notification is sent to the users who were added.

4.11. Setting Matchmaking Session Criteria

Parameters such as criteria and additional information searched for by other clients are set in MatchmakeSession class objects. You can also reset settings with the MatchmakeSession::Reset function.

The following table lists the parameters that can be set.

Table 4.1. Parameters That Can Be Specified to a Matchmaking Session
Name Description Initial Value Settings Function
Game mode A number that indicates matchmaking modes such as ranked matches, free play, and co-op mode. Games are free to use any values. Using game modes to filter matchmaking sessions can enhance search performance on the server. We recommend using as many specific game mode classifications as is feasible for your application. 0 SetGameMode
Matchmaking system type The matchmaking type. (Either anyone can join or only the friends of the matchmaking session owner can join.) Supports MATCHMAKE_SYSTEM_TYPE_ANYBODY, MATCHMAKE_SYSTEM_TYPE_FRIEND. When MATCHMAKE_SYSTEM_TYPE_ is specified, the matchmaking session is automatically closed to new participants when the owner logs out from the game server. However, it is not automatically closed if FriendOnlyParticipationPolicyArgument::WithoutClose is specified for the second argument of the SetMatchmakeSystemType function. MATCHMAKE_SYSTEM_TYPE_INVALID SetMatchmakeSystemType
Attributes Attribute values that a game can use as its own search criteria, such as a level, the number of rounds, and the purpose of a match. Up to six attributes can be specified. All 0 SetAttribute
Maximum number of participants The maximum number of participants for a matchmaking session. No more than the maximum number of participants can join a matchmaking session. 0 SetMaxParticipants
Gathering flags Flags that specify options for a gathering. The GatheringFlags::MigrateOwner flag may be set to specify if automatic owner migration occurs when the matchmaking session owner leaves a matchmaking session (by logging out from NGS or when executing the EndParticipation function). 0x0 SetFlag and ClearFlag
Application-defined data Data that can be freely used by applications. For example, this parameter can be set with up to 512 bytes of data that does not need to be included in the search criteria, such as the matchmaking session state. NULL SetApplicationBuffer
Description string A string that describes a matchmaking session. Applications can set this parameter with any value up to 256 characters. _T(“”) SetDescription
Invitation status flag Specifies the invitation status of a matchmaking session when it is registered. If this parameter is true, a session waits for new participants when it is registered. If it is false, a session is closed to new participants when it is registered. true SetOpenParticipation
Game progress score Application-defined value that is used if MATCHMAKE_SELECTION_METHOD_PROGRESS_SCORE is set as the matchmaking session selection method. MAX_PROGRESS_SCORE SetProgressScore
Options The options enumerated in MatchmakeFlags::MatchmakeSessionOption0 to add to the matchmaking session. MATCHMAKE_SESSION_OPTION0_NONE SetOption0Flag
Matchmaking parameters Parameters to add to the matchmaking session for use when the matchmaking session selection method is set to MATCHMAKE_SELECTION_METHOD_SCORE_BASED. MatchmakeParam SetMatchmakeParam
User password A password required to join a matchmaking session. User passwords can be up to MAX_MATCHMAKE_SESSION_USER_PASSWORD_LENGTH (32) characters in length. If you specify an empty string, no password will be set for the matchmaking session. _T(“”) SetUserPassword
ID of a persistent gathering to associate The ID of a persistent gathering to associate with the matchmaking session. Use the PersistentGathering::GetMatchmakeSessionCount function to get the number of matchmaking sessions associated with a persistent gathering. Specify INVALID_GATHERINGID to leave the matchmaking session unassociated with any persistent gathering. INVALID_GATHERINGID SetReferPersistentGatheringId

Comments

If a client registers a matchmaking session to wait for new participants, that client may not get a chance to start P2P communication before another client attempts to start communicating with it. If your application joins a matchmaking session and then uses P2P communication, implement it to register the session closed to new participants and prepare for P2P communication before you change the session to wait for new participants.

Comments

Do not directly change the class variables of the MatchmakeSession class or its parent, the Gathering class, using setting functions other than those in Table 4.1 and MatchmakeSession::Reset, which resets criteria. Operations in this situation are not guaranteed.

4.12. Setting the Search Criteria and Range

Search criteria are set in MatchmakeSessionSearchCriteria class objects. Table 4.2 shows the search criteria that can be set in MatchmakeSessionSearchCriteria. The configured search criteria are combined using a bitwise AND. You can also restore the default settings by using the MatchmakeSessionSearchCriteria::Reset function.

Table 4.2. Specifiable Search Criteria
Name Description Initial Value Settings Function
Game mode A number that represents types of games. You must specify a value for this option. None. SetGameMode
Matchmaking system type The matchmaking type. (Either anyone can join or only the friends of the matchmaking session owner can join.) When MATCHMAKE_SYSTEM_TYPE_FRIEND is specified, the server checks whether the owner is a friend of the local host. Specifying this item is required. None. SetMatchmakeSystemType
Attributes Games can specify up to six of these attributes as independent search criteria. If not specified, the type condition matches any value. Attribute values are evaluated all at once without concern for the index order. Attribute values can be specified with a range by using the SetAttributeWithRange function. Arbitrary value SetAttribute, SetAttributeWithRange
Flag for excluding full sessions Specifies whether to exclude full matchmaking sessions. False SetVacantOnly
Flag for excluding sessions with undetermined hosts Specifies whether to exclude sessions for which a P2P communication host has not been determined. True SetExcludeNonHostPid
Flag for excluding closed sessions Specifies whether to exclude matchmaking sessions that are closed to new participants. True SetExcludeLocked
How to select the matchmaking session Specifies how to select which matchmaking session to join when multiple matchmaking sessions satisfy the search criteria. (Used only with automatic matchmaking.) MATCHMAKE_SELECTION_METHOD_RANDOM SetSelectionMethod
ID of a persistent gathering to associate Matchmaking sessions associated with the specified persistent gatherings will be included in searches. Specify INVALID_GATHERING to match on any value. INVALID_GATHERING SetReferPersistentGatheringId

To specify a search range, set an offset and the maximum size of the search results in a ResultRange class object. By default, the offset is 0 and the maximum size of an obtained list is 100. Although matchmaking session IDs are sorted in ascending order in the lists that can be obtained, the server randomly rearranges data that matches the search criteria before returning the result to the client when RESULTRANGE_ANY_OFFSET is specified as the offset. Use a maximum list size of 100 or less.

If your implementation filters search results from the game server without specifying any search criteria, it cannot perform matchmaking effectively because there is no guarantee that it can get a matchmaking session that meets the desired criteria. Consequently, include search criteria that can be matched perfectly (such as the region and round number), by using attributes that you can specify with the SetAttribute function on the client without filtering.

4.13. Notes About Matchmaking Search

Matchmaking search is processing-heavy. Implement matchmaking conditions so that existing matchmaking sessions that are waiting for participants are filled before creating a new matchmaking session. If matchmaking conditions are divided into too many small parts, it can be difficult to complete the gathering process, users are forced to wait longer, and the user experience deteriorates.

Also, actively control to remove the gathering from the search pool. When the maximum number of participants in a matchmaking session is reached, use MatchmakeSessionSearchCriteria::SetVacantOnly to automatically remove the gathering from the search target. If a game starts before the maximum number of participants is reached, and it is obvious that other players are no longer joining the session during the game (after the game itself started for games that run for a long time), call the MatchmakeExtensionClient::CloseParticipation function to close the gathering, and remove it from the search target.

Matchmaking sessions can be password locked to limit the session to a defined group of users. If a matchmaking session restricted in this manner is shown in the general matchmaking search results, a large number of restricted matchmaking sessions may be displayed in the search results. When this occurs, users may reload the search results repeatedly to find open matchmaking sessions, increasing server load and decreasing the quality of the user experience. As a result, restricted matchmaking sessions are not displayed in the matchmaking list during searches. Alternatively, we recommend providing a separate method to search for unrestricted matchmaking sessions.

We also recommend an implementation to reduce server load when you want users to add additional people to the session outside of the game by showing the gathering ID as a code, and searching for this code using the MatchMakingClient::FindByID function, instead of storing the search code in a tag to search.

4.14. Setting a Matchmaking Session Password

Matchmaking sessions can be created with a password restriction. There are two types of passwords: a user password, and a system password. A user password is set by the player; the system password is set by the server. The MatchmakeSession::SetUserPassword function is used to set a user password for a matchmaking session being registered on a server. The MatchmakeExtensionClient::GenerateMatchmakeSessionSystemPassword function is used to set a system password for a matchmaking session already registered on the server. NotificationEvents::MatchmakeSessionSystemPasswordSet is notified to members of the matchmaking session when the system password is set. Use the MatchmakeExtensionClient::ClearMatchmakeSessionSystemPassword function to remove the system password. NotificationEvents::MatchmakeSessionSystemPasswordClear is notified when the system password is removed. The correct password must be specified to join a matchmaking session protected by a user password or system password. The JoinMatchmakeSessionParam object with a set password is selected in the JoinMatchmakeSessionParam::SetUserPassword or JoinMatchmakeSessionParam::SetSystemPassword function, for the MatchmakeExtensionClient::JoinMatchmakeSession function taking JoinMatchmakeSessionParam as an argument. A matchmaking session protected by a system password is automatically hidden from MatchmakeExtensionClient::BrowseMatchmakeSession. These password protected matchmaking sessions can be searched using MatchMakingClient::FindByID. The MatchmakeSessionSearchCriteria::SetExcludeUserPasswordSet function is used to set whether the MatchmakeExtensionClient::BrowseMatchmakeSession function shows matchmaking sessions protected by user passwords. The system password is useful when a session is waiting for certain players to join. Players that are unexpectedly disconnected from a server can use the system password generated by the MatchmakeExtensionClient::GenerateMatchmakeSessionSystemPassword function to rejoin the same matchmaking session. User passwords and system passwords cannot be obtained from matchmaking sessions retrieved using the MatchMakingClient::FindByID or MatchmakeExtensionClient::BrowseMatchmakeSession functions. The MatchmakeSession::GetUserPassword function always returns an empty string when called on matchmaking sessions retrieved from the server. However, you can use the MatchmakeSession::GetUserPasswordEnabled and MatchmakeSession::GetSystemPasswordEnabled functions to determine whether a user password or system password has been set.

4.15. Changing Registered Matchmaking Sessions

Some criteria can be changed even after the owner of a matchmaking session is registered with the game server.

4.15.1. Inviting Clients to Join a Matchmaking Session

Use the MatchmakeExtensionClient::OpenParticipation function to invite clients to join a matchmaking session. This function takes two arguments: a pointer to a ProtocolCallContext object, and the ID of the matchmaking session to invite clients to join.

When asynchronous processing succeeds, other clients can join the matchmaking session. (When searching for matchmaking sessions, the invitation status flag is true.) However, new clients cannot join after the maximum number of matchmaking participants is reached.

4.15.2. Closing a Matchmaking Session to New Clients

Although new clients cannot join a session after it has reached its maximum number of participants, a session can also be closed to new clients even if it has not reached the maximum number of participants.

Use the MatchmakeExtensionClient::CloseParticipation function to close a matchmaking session to new clients. This function takes two arguments: a pointer to a ProtocolCallContext object, and the ID of the matchmaking session to close to new clients.

When asynchronous processing succeeds, other clients can no longer join the matchmaking session. (When searching for matchmaking sessions, the invitation status flag is false.) However, clients that have already joined are not affected. Also, note that a ParticipationEvents::Participate notification may arrive after a successful call to this function due to differences in when the NotificationEvents::ParticipationEvent event and session participation close process are handled.

Note

Be careful if your application is designed to have users join a P2P session after joining a matchmaking session. Participation in the P2P session may not complete for some time after closing participation in the matchmaking session because the NAT traversal and join P2P session processes themselves take some time to complete. If a client is denied participation when attempting to join a P2P session, it can have an extremely negative effect on the efficiency of the matchmaking process. It is particularly important to consider this effect if you close participation in a matchmaking session before the maximum number of participants has joined. In this case, implement handling using a NotificationEvents::ParticipationEvent notification and make sure that you do not deny participation in the P2P session if the number of participants in the matchmaking session and the number of participants in the P2P session are different.

4.15.3. Transferring Matchmaking Session Owner Authority

Use the MatchMakingClient::MigrateGatheringOwnership function to transfer ownership of a matchmaking session to another client. This function is usually used when the owner leaves the matchmaking session. When GatheringFlags::MigrateOwner is specified in the gathering flag, there is no need to call the MatchMakingClient::MigrateGatheringOwnership function when leaving, because ownership transfer occurs automatically. Only existing members of a matchmaking session can become the new owner.

This function takes the following arguments: a pointer to a ProtocolCallContext object, the ID of the matchmaking session for which to transfer ownership, and a list of principal IDs for the clients to which ownership is transferred. If the list of principal IDs is empty, a new owner is automatically selected from the clients that have joined the matchmaking session. (As a general rule, use this approach.)

The MatchMakingClient::UpdateGatheringOwnership or MatchMakingClient::UpdateSessionHost function can be used by a gathering member to take ownership, if the GatheringFlags::ChangeOwnerByOtherHost flag is set in the matchmaking session gathering flags. These APIs can be used to make the P2P host and gathering owner the same.

4.15.4. Updating Matchmaking Sessions

Use the MatchmakeExtensionClient::UpdateMatchmakeSession function to make changes to matchmaking session information. The overload of the function that takes GatheringHolder as an argument updates all of the matchmaking session parameters except for the ID, owner, P2P communication host, gathering flags, ID of the related persistent gathering, and common key for P2P communications. The matchmaking system type can only be changed between MATCHMAKE_SYSTEM_TYPE_ANYBODY and MATCHMAKE_SYSTEM_TYPE_FRIEND. The overload of the MatchmakeExtensionClient::UpdateMatchmakeSession function that takes UpdateMatchmakeSessionParam as an argument only updates the specified matchmaking session parameter.

4.15.5. Changing Attributes

There are two ways to change attributes: either individually with the MatchmakeExtensionClient::ModifyMatchmakeSessionAttribute function, or all at the same time with the MatchmakeExtensionClient::UpdateMatchmakeSessionAttribute function. The ModifyMatchmakeSessionAttribute function takes the following arguments: a pointer to a ProtocolCallContext object, the ID of the matchmaking session to change, the index of the attribute to change, and the new attribute value. The UpdateMatchmakeSessionAttribute function takes the following arguments: a pointer to a ProtocolCallContext object, the ID of the matchmaking session to change, and an array of new attribute values.

4.15.6. Changing Application-defined Data

Use the MatchmakeExtensionClient::UpdateApplicationBuffer function to change application-defined data. This function takes the following arguments: a pointer to a ProtocolCallContext object, the ID of the matchmaking session to change, and the new data.

4.15.7. Deleting a Matchmaking Session

Use the MatchMakingClient::UnregisterGathering function to delete a matchmaking session. This function takes the following arguments: a pointer to a ProtocolCallContext object, and the ID of the matchmaking session to delete. The matchmaking session is deleted automatically in the following situations.

  • When the matchmaking session owner logs out from the game server when GatheringFlag::OwnerMigration is not set in the gathering flag.
  • The number of participants in the matchmaking session becomes 0.

To prevent meaningless matchmaking sessions from being left on the game server, use the MatchMakingClient::UnregisterGathering function to delete unnecessary matchmaking sessions.

4.16. Joining Using the Friend Presence Library

4.16.1. Overview

Use the friend presence library to share the gathering participation state in NEX with friends as presence. The application or friend list can get presence that is shared with friends, and can use that information to join gatherings that a friend is currently participating in. The friend presence library includes the following two processes for helping to join in.

  • Sharing Presence Store parameters for the MatchmakeSession object that matches the NEX gathering participation state in the nn::friends:GameMode structure, and update the join-in-capable status using the nn::friends:UpdateGameMode function.
  • Getting and Monitoring Presence, and Joining in The client joining an existing session monitors presence changes for the friends of the user (that is, matchmaking sessions they are participating in) to discover friends the user can join with. Then it specifies a gathering ID that includes that presence, and joins the matchmaking session that the friend is participating in using the MatchmakeExtensionClient::JoinMatchmakeSession function.

4.16.1.1. Joining-in Through the Friend List

The friend list gathers the presence of friends that are publicizing their status, and displays that status. Both friends, if online, see each other's status and the games they both are playing, even if they are not playing the same game.

If a friend is online, and the public presence indicates that friends allow join-in, the Join game your friend is playing button on that friend's card is enabled. Pressing that button starts the game that the friend is playing, which also ends any game that the first player is already playing.

If an application was started from the friend list, the application can get the fact that it was started from the friend list, and can get the friend key of the friend chosen from the list, after it starts. It gets the current presence of the friend from that friend key, and then uses NEX to use that information to join the gathering that the friend is participating in.

4.16.1.2. Joining an Application That Has the Same Join-in Game ID

If both players are playing a game that has the same join-in game ID, the application can directly get the parameters for the presence that the friend is publicizing. It uses those parameters to determine whether the friend is accepting the join-in, and uses NEX to join the gathering that the friend is participating in.

The friend presence library helps the player determine whether the friend's presence accepts the join-in, and helps to monitor changes in presence.

4.16.2. Implementation

4.16.2.1. Incorporating Join-In Information Into Icon Data

In the BSF file, set the join-in game ID in JoinGameId, and set the join-in game mode mask in JoinGameModeMask. For more information about these settings, see the ctr_makebanner manual.

The join-in game ID uses the NEX game server ID. Applications that have set the same value for the join-in game ID can share presence between friends.

The game mode mask is specified as a bit mask, with the lowest value bit being mode 0, and the highest value bit being mode 63, indicating the ability to join. This value is used only to determine when an application is started from the friend list, and has no effect on operations after the application is started.

Use the CTR Master Editor to confirm this value.

An application must be restarted from the HOME Menu for the join-in game ID set in its icon data to take effect. When an SD Card is inserted in the system, the HOME Menu caches icon data on the SD Card. Updates to that data sometimes do not take effect. When this happens, delete the icon data cache. For more information about deleting the icon data cache, see "Using Debug Functionality" under "HOME Menu" in the manual that comes with the CTR-SDK package.

Comments

You can access the HOME Menu from either of the following locations.

  • The list of menus in index.html of the CTR-SDK package
  • CTR_SDK\documents\DevHomeMenu\HomeMenu.html

4.16.2.2. Preparing for Joining

To share presence between friends by using the friend library, both friends must be online and must both set the same join-in game ID.

Although a player can share presence with friends even when the player was logged in in response to a background login request from the system, the online state might not be maintained if the application does not issue a login request. Send a login request using the nn::friends::Login function before using functionality related to joining.

4.16.2.3. Sharing Presence (Implementation for the Party Being Joined)

To correctly communicate the status of the player that indicates they can accept joining, use the nn::friends::UpdateGameMode function to update the presence of the player whenever the NEX gathering participation status of the player changes.

Specify the following option for each element of the nn::friends:GameMode structure.

  • joinAvailabilityFlag: Specifies whether the game on the local host is available for friends in the matchmaking session to join. If it does not permit joining, the game determines that joining is not possible even if all of the following parameters meet the requirements for joining. Use the values in the JoinAvailability enumerator.
Table 4.3. Relationship Between joinAvailabilityFlag and Whether Joining Is Possible
joinAvailabilityFlag JOIN_AVAILABILITY_JOINABLE JOIN_AVAILABILITY_JOINABLE_APP_ONLY JOIN_AVAILABILITY_NOT_JOINABLE
Join game that is being played button on the friend list. Enabled if conditions are met. Always disabled. Always disabled.
nn::friends::FriendPresence::IsJoinable() true if conditions are met. true if conditions are met. Always false.
  • matchmakeSystemType: The type of matchmaking the local host is participating in. Store the matchmaking system type value in the MatchmakeSession object while participating.
  • joinGameId: An ID used to distinguish what game titles allow players to join. UpdateGameMode ignores this value even if specified, and the join-in game ID specified in the icon data continues to be used.
  • joinGameMode: A value used to distinguish what game modes allow players to join. While a 32-bit range can be used in NEX, for the friend list or friend presence library to determine that joining is possible, you must use a value between 0 and 63. Store the game mode value in the MatchmakeSession object while participating.
  • joinGameMode: Specifies the principal ID of the owner of the local host's matchmaking session. Store the principal ID of the owner in the MatchmakeSession object while participating. When the matchmaking system type is FRIEND, update GameMode if the owner has changed. Knowing whether the player has a friend relationship with the owner is necessary for determining whether joining is possible.
  • joinGroupId: Specifies the ID of the local host's matchmaking session. Store the gathering ID value in the MatchmakeSession object while participating.
  • applicationArg: Information that can be freely defined by applications.

While there is no limit to the frequency with which you can call the UpdateGameMode function, to notify the server or a friend of the updated information, an interval of at least 10 seconds from the previous update is necessary. For more information, see 4.3.5.2. Synchronizing the Friend Server or Friend Data in the CTR Programming Manual: Wireless Communication.

Note that even if you renew the presence of a player more often, there is still a delay before it is communicated to a friend.

4.16.2.4. Getting and Monitoring Presence (Implementing for the Joining Party)

You can use the nn::GetFriendPresence function to get a friend's presence. Use the nn::friends::FriendPresence structure that you get to determine the join-in-capable status of a friend with the nn::friends::FriendPresence::IsJoinable function. When you use this function, specify a bit mask in the function parameters to indicate which game modes the player can join. If you determine that the player can join, you can specify the NEX gathering ID as the value of the joinGroupId member and execute the join operation on that gathering.

Handle changes in friend presence by using the nn::friends::AttachToEventNotification or nn::friends::GetEventNotification function to monitor presence change notifications. When a presence change notification comes, use the IsJoinable function to determine whether a player can join again.

4.16.2.5. Handling Start From the Friend List

If an application is started from the friend list, the nn::friends::IsFromFriendList function returns true. In this case, the FriendKey for the selected friend is also stored in the buffer passed to a parameter. After getting the parameter, get the presence of the friend that the FriendKey indicates, and rapidly transition to the join-in sequence.

4.16.3. Notes

  • Even if the application uses presence to determine that the player can join and then joins the gathering, perform a failure determination as normal during the joining process. The join-in status available from presence does not necessarily indicate the correct status in real time. The status of the player may change while the join operation is in progress.
  • Set only the needed bits in the bit mask for indicating join-in game modes. Determining in previous versions of the application that the player can join in a wider than necessary range may hinder the introduction of new game modes if the same join-in game ID is used in later versions or localized editions.
  • Even if the application does not support join-ins from the friend list, if friend presence is shared by the application, the join-in game ID must be included in the icon data using makebanner. When this happens, set the game mode mask for the icon data to 0, and specify JOIN_AVAILABILITY_JOINABLE_APP_ONLY as the joinAvailabilityFlag value when updating presence. If these settings are not correct, the Join game that is being played button on the friend list is enabled, but it is impossible to start the game.

4.17. Blacklists

Applications can use blacklists to prevent harassment by specific users. By using a blacklist, a user can:

  • Block users registered to a blacklist from joining the matchmaking session of the local system.
  • Block the local system user from joining matchmaking sessions in which users registered to the blacklist are participating.
  • Configure applications to prevent users registered to the blacklist from getting status. (This feature is the privacy filter feature.)

This is always enabled. You cannot enable or disable it in the application. If you want to disable the blacklist feature due to the design of your application, please contact Nintendo at support@noa.com.

A single player can register up to 100 other players on their blacklist, and has one blacklist per game server (and per application). If a player blacklists more than 100 people, the earliest entries on the blacklist are deleted in the order in which they were registered. (This method is called the first-in-first-out (FIFO) method.) You decide whether to manage the blacklist inside the application on an application-by-application basis.

The MatchmakeExtensionClient::GetPlayingSession and MatchmakeExtensionClient::FindPersistentGatheringByParticipant functions always return an empty list when searching for players who are registered to the local host’s blacklist. However, it is not possible to detect whether other participants in that gathering are on the blacklist of the local system.

The MatchmakeExtensionClient::BrowseMatchmakeSession and MatchMakingClient::FindByID functions, among others, also do not check whether a participating user is registered to the blacklist of the local system, or has registered the user of a local system to a blacklist. Consequently, you cannot determine whether users in a session are registered to the blacklist of the local system, or the user of the local system is registered to their blacklist, until the call to the MatchmakeExtensionClient::JoinMatchmakeSession function. Note that the primary purpose of the privacy filter is to prevent harassment by particular users.

Code 4.6. Blacklist Management API

// Add the specified player to the blacklist on the game server.
qBool MatchmakeExtensionClient::AddToBlackList(
                                    ProtocolCallContext* pContext,
                                    const qList<PrincipalID>& PrincipalIDList);

// Delete the specified player from the blacklist on the game server.
qBool MatchmakeExtensionClient::RemoveFromBlackList(
                                    ProtocolCallContext* pContext,
                                    const qList<PrincipalID>& principalIDList);

// Clear the blacklist.
qBool MatchmakeExtensionClient::ClearBlackList(ProtocolCallContext* pContext);

// Get players that the local host has registered on its own blacklist.
qBool MatchmakeExtensionClient::GetMyBlackList(
                                    ProtocolCallContext* pContext,
                                    qList<PrincipalID>* pPrincipalIDList);

4.18. Persistent Gatherings

A persistent gathering is a mechanism for matchmaking within a specific group of users. You can make a persistent gathering room (where, for example, only students at a specific school can participate), and matchmake within that room.

Although some features are similar to friend features, a user can join a persistent gathering without needing to establish any friendships with anyone. This functionality enables game developers to set up official persistent gatherings for particular game titles, hold tournaments, and so on.

Once created, persistent gatherings remain on the server until they are explicitly deleted. Participation in persistent gatherings is similarly permanent until explicitly modified (when using the default persistent gathering settings). To matchmake users in a persistent gathering with each other, add the ID of that persistent gathering as the ID to associate with the matchmaking session when registering the matchmaking session and then search for or have users join sessions using that ID.

Although persistent gatherings are a type of gathering, whether the join status is permanent is a significant difference from matchmaking session gatherings.

The following examples show possible uses for persistent gatherings.

  • Tournaments, rankings, and other uses in an official persistent gathering
  • Persistent gatherings that play only on specific courses or under certain rules
  • A persistent gathering consisting of a students at a particular school, with matchmaking between the students

Persistent gatherings exist independently for each game.

4.18.1. Differences Between Persistent Gatherings and Matchmaking Sessions

Persistent gatherings and matchmaking sessions differ not only in their lifespans, but also in the following other ways.

Table 4.4 Differences Between Persistent Gatherings and Matchmaking Sessions
Differences Persistent Gathering Matchmaking session
Deletion timing The number of members becomes 0 [note 1]. The UnregisterGathering function is called. The number of members becomes 0. The UnregisterGathering function is called.
Leaving timing The EndParticipation function is called [note 2]. The EndParticipation function is called. The user is logged out from the game server.
Number of participants Unlimited by default. (A limit can be set.) Number of clients using P2P communication.
Notification from the server. None. A notification is pushed when a user joins or leaves.
Messaging Only possible if the maximum number of participants is set to 32 or fewer (MessagingClient::SendChat). Possible. (Use the MessagingClient::SendChat function.)
P2P communication None. Register and then join a separate matchmaking session, and then switch to P2P mode. Yes
Owner migration None. Yes
Blacklist None. Yes
Deadline None. However, it is possible to set a period during which joining is possible. Yes

[1] You can make the gathering persist even when the number of participants reaches 0 by setting GatheringFlags::AllowNoParticipant in the gathering flags.

[2] You can make users leave a gathering automatically when they are disconnected from the game server (including logging out) by setting GatheringFlags::NoPersistentParticipation in the gathering flags.

4.18.2. Creating, Deleting, and Updating Persistent Gatherings

To create a persistent gathering, set the conditions for the persistent gathering in the PersistentGathering class object, and execute the MatchmakeExtensionClient::CreatePersistentGathering function. (Do not set any items other than those in Table 4.5 Persistent Gathering Settings. Setting other items may cause unintended results.) If the asynchronous process in the MatchmakeExtensionClient::CreatePersistentGathering function succeeds, a gathering ID is assigned by the game server so that the persistent gathering can be identified. The user who calls the CreatePersistentGathering function becomes the owner of that gathering, and automatically joins the gathering. Each user can create up to PERSISTENT_GATHERING_CREATION_MAX (4) persistent gatherings, and can be a member of up to PERSISTENT_GATHERING_PARTICIPATION_MAX (16).

The owner of a community can update that community by using the MatchmakeExtensionClient::UpdatePersistentGathering function, and can delete it by using the MatchMakingClient::UnregisterGathering function. It is also possible to delete a persistent gathering that has more members than just the owner. When a persistent gathering is deleted, all users who are members of the community leave it.

When an official persistent gathering is created, the owner's principal ID takes a special value (101), and the client that created the gathering can no longer update or delete the gathering. Update or delete the gathering from NMAS. (NMAS is discussed in more detail later.)

Official persistent gatherings created in the development environment are automatically copied into the Lotcheck environment. Please make the required official persistent gatherings available when Lotcheck starts. This will not be copied into the production environment.

Table 4.5. Persistent Gathering Settings
Name Description Initial Value Settings Function
Persistent gathering type Specify the persistent gathering type: anybody can join, password is required to join, or official persistent gathering. Open SetPersistentGatheringType
Attributes Games can specify up to six of these attributes as independent search criteria. 0 SetAttribute
Maximum number of participants When 0 is specified, there is no limit to the maximum number of participants. 0 SetMaxParticipants
Application-defined data Data that can be freely used by applications. You can set up to 512 bytes of data that does not need to be searchable in this parameter, such as the status of the persistent gathering. NULL SetApplicationBuffer
Description string A string describing the persistent gathering. Applications can set this parameter with any value up to 256 characters. _T(“”) SetDescription
Date from which users can join Gets the date and time from which users can join the persistent gathering. If DateTime::Never() is specified, there is no limit. DateTime::Never() SetParticipationStartDate
Last day on which users can join Gets the deadline (date and time) for joining the persistent gathering. If DateTime::Never() is specified, there is no limit. DateTime::Never() SetParticipationEndDate

4.18.3. Searching Persistent Gatherings

The following functions can be used to search persistent gatherings. If a result of a search from the FindPersistentGatheringByParticipant function is on the blacklist of the local host, or if the target participant has used the MatchmakeExtensionClient::UpdatePrivacySetting function to set the status of their participation in the persistent gathering to 'private', a blank list is returned. Note: Currently, NEX does not support searching for persistent gatherings by attributes.

Code 4.7 Functions for Searching Persistent Gatherings

// Search by ID.
MatchmakeExtensionClient::FindPersistentGatheringByGatheringID(
                                    ProtocolCallContext *pContext,
                                    qList<GatheringID> gatheringIdList,
                                    qList<PersistentGathering> *pPersistentGatheringList);

// Search by participant.
MatchmakeExtensionClient::FindPersistentGatheringByParticipant(
                                    ProtocolCallContext *pContext,
                                    PrincipalID principalId,
                                    const ResultRange& resultRange,
                                    qList<PersistentGathering>* pPersistentGatheringList);

// Search official persistent gatherings. (The persistent gathering type is PERSISTENT_GATHERING_TYPE_OFFICIAL.)
MatchmakeExtensionClient::FindOfficialPersistentGathering(
                                    ProtocolCallContext *pContext,
                                    qBool isAvailableOnly,
                                    const ResultRange& resultRange,
                                    qList<PersistentGathering>* pPersistentGatheringList);

// Search by the principal ID of the owner.
qBool MatchmakingClient::FindByOwner(ProtocolCallContext *pContext,
                                    PrincipalID pidOwner,
                                    const ResultRange& resultRange,
                                    qList<GatheringHolder> *plstGatherings);

4.18.4. Joining and Leaving Persistent Gatherings

Use the MatchmakeExtensionClient::JoinPersistentGathering function to join a persistent gathering, and the MatchmakeExtensionClient::EndParticipation function to leave a persistent gathering. Unlike in a matchmaking session, the owner of a persistent gathering is not notified when a member joins or leaves. A user can only join up to 16 (PERSISTENT_GATHERING_PARTICIPATION_MAX) persistent gatherings. If the user tries to join more gatherings, the asynchronous process fails with QERROR(RendezVous, PersistentGatheringParticipationMax).

4.18.5. Persistent Gathering Codes

To display an identifier for the persistent gathering in the user interface as an ID, you must convert the gathering ID of the persistent gathering to a persistent gathering code. The persistent gathering code is a 14-digit, decimal, integer HMAC value that is assigned based on the gathering ID and unique access key for the game. You must query the game server to determine whether a persistent gathering exists, even if the IsValidPersistentGatheringCode function determines that the persistent gathering code is valid. You can still use the persistent gathering code conversion function shown in the following code example even when you are not logged in to the game server.

Code 4.8. Persistent Gathering Code Conversion Functions

// Sets the persistent gathering code HMAC key. Specifies the unique access key for a game.
static void MatchmakingClient::SetPersistentGatheringCodeKey(const String& strKey);

// Clears the persistent gathering code HMAC key.
static void MatchmakingClient::ClearPersistentGatheringCodeKey();

// Converts a gathering ID to a persistent gathering code.
static qUnsignedInt64 MatchmakingClient::GatheringIdToPersistentGatheringCode(GatheringID gatheringId);

// Converts a persistent gathering code to a gathering ID.
static GatheringID MatchmakingClient::PersistentGatheringCodeToGatheringId(qUnsignedInt64 persistentGatheringCode);

// Checks whether the community code is valid.
static qBool MatchmakingClient::IsValidPersistentGatheringCode(qUnsignedInt64 persistentGatheringCode);

4.18.6. Connection Between Matchmaking and Ranking

While persistent gatherings are permanent, it is not possible to do matchmaking at the persistent-gathering level. To perform matchmaking in connection with a persistent gathering, you must register a separate matchmaking session (a persistent gathering matchmaking session) and associate the gathering ID of the persistent gathering with that matchmaking session. When registering a persistent gathering matchmaking session, use the MatchmakeSession::SetReferPersistentGatheringId function to set the ID of the persistent gathering to associate with the matchmaking session. All other settings have no difference from regular matchmaking.

Registering a persistent gathering matchmaking session increments the persistent gathering matchmaking session count. You can get the count from the PersistentGathering::GetMatchmakeSessionCount function. (When the session is deleted, the count is decremented.)

Comments

To associate a persistent gathering with a matchmaking session in NEX 3.7 and earlier, you had to set the matchmaking system type to MATCHMAKE_SYSTEM_TYPE_PERSISTENT_GATHERING and set the ID of the persistent gathering to associate as the 0th attribute when registering a matchmaking session. To maintain compatibility in NEX 3.8 and later, set the matchmaking system type to MATCHMAKE_SYSTEM_TYPE_PERSISTENT_GATHERING and set the ID of the persistent gathering to associate as the 0th attribute. To automatically set the 0th attribute of new matchmaking sessions to the ID of the persistent gathering to associate when they are registered on the server, specify INVALID_GATHERINGID as the ID of the persistent gathering to associate. Call the MatchmakeSession::SetReferPersistentGatheringId function on matchmaking sessions retrieved from the server to get the ID of the associated persistent gathering. The number of persistent gathering matchmaking sessions being held is also counted.

If you are ranking users in a persistent gathering (by using a community ranking), you can use the gathering ID of the persistent gathering as the category. However, it is not possible to use the same categories as in regular ranking. If your persistent gathering uses the 0th to 10th categories for regular ranking, try to ensure that the persistent gathering rankings are assigned to the 11th and later slots.

4.18.7. NEX Server Management System (NMAS)

Persistent gatherings can be created, edited, and deleted using the persistent gathering management functions in the NEX Server Management System (NMAS). The tool supports both the development environment and the production environment.

Use the following URL to access NMAS.

https://nmas.app.nintendowifi.net/nmas/

Use the same login ID and password that you use for OMAS.

4.19. Handling Notification Events

A notification event is a message that is sent from a game server to another client when a particular event occurs on the game server. When a client joins a matchmaking session, for example, a message notifies the other clients that have already joined that session.

For a client process to receive notification events, RendezVous::RegisterNotificationEventHandler must register a NotificationEventHandler with the client process after it has logged in to the game server. Each time the client process receives a notification event after the handler has been registered, the event is sent to the handler and the ProcessNotificationEvent system callback is invoked. Although this callback ignores all received notification events by default, you can customize how notification events are processed by sub-classing NotificationEventHandler and re-implementing the system callbacks.

The following values are passed to the ProcessNotificationEvent system callback: the principal ID of the client that generated the event, the event type, and a NotificationEvent class object that stores up to three parameters. NEX uses the following event types (which can be obtained with NotificationEvent::GetType).

Code 4.9. Subclassing NotificationEventHandler

// Event handler for getting notifications from NGS.
class MyNotificationEventHandler : public NotificationEventHandler {
public:
    void ProcessNotificationEvent(const NotificationEvent &oEvent){

        switch (oEvent.GetType())
        {
        case NotificationEvents::ParticipationEvent:
            switch (oEvent.GetSubType())
            {
            case ParticipationEvents::Participate:
                NN_LOG("%u join %u\n", oEvent.GetParam2(), oEvent.GetParam1());
                break;
            case ParticipationEvents::EndParticipation:
                NN_LOG("%u end %u\n", oEvent.GetParam2(), oEvent.GetParam1());
                break;
            case ParticipationEvents::Disconnect:
                NN_LOG("%u disconnect %u\n", oEvent.GetParam2(), oEvent.GetParam1());
                break;
            default:
                NN_LOG("unspoorted participation event\n");
                break;
            }
            break;
        case NotificationEvents::OwnershipChangeEvent:
            NN_LOG("matchmakesession %u changed owner to %u\n", oEvent.GetParam1, oEvent.GetParam2());
            break;
        case NotificationEvents::GameNotificationEvent1:
            NN_LOG("game specific event 1\n");
            break;
        case GameServerMaintenance:
            NN_LOG("game server maintenance event\n");
            break;
        default:
            NN_LOG("unsupported notification event\n");
            break;
        }
    }
};

4.20. Using Game-Specific Notification Events

Games can independently define notification events and send them to friends who are logged in to the same game server. For more information about how these notification events are handled when they are received, see 4.19. Handling Notification Events. This feature has been designed to account for the server, and assumes that implementations send events from users to their communication partners. Do not send events more often than that. Specifically, this feature has the following restrictions.

  • It cannot be used to send data other than events from users. One example of this would be the exchange of data during an online game that was originally sent and received through P2P communication.
  • Restrict events to being sent no more than 10 times a minute to prevent successive user operations from resulting in too many transmissions.
  • Use NotificationEvents::GameNotificationEvent 1–8 as the game-defined event types.

4.20.1. Registering Notification Events With the Server and Sending Them to Friends

Use the MatchmakeExtensionClient::UpdateNotificationData function to notify friends of game-specific events. This function takes the following arguments: a pointer to a ProtocolCallContext object, a notification type, and notification data defined independently by a game (two qUnsignedInt32 values and a single string of up to 256 characters). To prevent notification types from overlapping with the system-defined event types, set the values between NotificationEvents::GameNotificationEvent1 and NotificationEvents::GameNotificationEvent8. When a client disconnects from the game server, every notification event that it registered is automatically deleted from the game server.

4.20.2. Getting Registered Notification Events

Use the MatchmakeExtensionClient::GetFriendNotificationData function to get friend notification events that have already been registered. This function takes the following arguments: a pointer to a ProtocolCallContext object, a pointer to a qList <NotificationEvent> that stores the asynchronous processing results, and the type of notification to get.

Comments

Use this function only when a client logs in, and then handle notification events while the client is logged in.

4.21. Handling Game Server Maintenance Notification Events

The client can be programmed to handle notification events that are triggered when game server maintenance is announced or begins. By handling these events, you can tell users that maintenance is about to start. The maintenance announcement and start events are sent to all terminals logged in to the game server. If a client connects after the announcement or start event has already been sent, the event is sent to the client after login.

WebAPI can be used to set whether a notification is made for the start of maintenance. The default is false. This stops accepting new matchmaking, regardless of whether clients sent the notification. For details, see enable_maintenance_notification in the changing matchmaking session settings(Section 12.2.2.9). Maintenance announcement events are only sent for the titles configured to do so. Contact Nintendo if you want to use the maintenance announcement event.

_images/Fig_Server_Maintenance.png

Figure 4.1. Maintenance Workflow and Notification Events

4.21.1. Handling a Maintenance Announcement Event

Approximately one hour before game server maintenance begins, a NotificationEvents::MaintenanceAnnouncement event is sent.
The NotificationEvent::GetParam1 function takes the maintenance start time in Unix Epoch Time. The server maintenance start time can be retrieved using the DataTime::FromUnixEpochTime function of the DataTime class.

The time in the event is in UTC. Note that in emergency situations it might not be possible to make the maintenance announcement one hour in advance.

4.21.2. Handling a Maintenance Start Event

If enable_maintenance_notification is enabled in the WebAPI matchmaking session configuration when the game server maintenance starts, NotificationEvents::GameServerMaintenance is sent as a start notification. After the event is sent, perform the following actions to stop the game server from receiving new matchmaking requests.

  • Stops receiving requests to create, join, and search for matchmaking sessions.
  • Stops receiving requests to register, join, and search for persistent gatherings.

Then, stop the game server around five to ten minutes later to perform the maintenance.

If matchmaking does not complete within five to ten minutes, the following kinds of actions are available. Determine the best solution for the specifications of your game.

4.22. Using Messaging Features

The messaging feature provides a general way for clients to exchange text and binary messages. Using reliable communication, instant messages are sent to specified users by using the game server. Messages can only be sent to users who are logged in to the game server.

This feature (including the server) was designed on the assumption that it will be used to send messages between users. Do not send messages more frequently than that. Specifically, this feature has the following restrictions.

  • It cannot be used to send data other than messages from users. One example of this would be the exchange of data during an online game that was originally sent and received through P2P communication.
  • Restrict events to being sent no more than 10 times a minute to prevent successive user operations from resulting in too many transmissions.

4.22.1. Sending Messages

Use the MessagingClient::SendInstant function to send a message to a particular client. This function takes the following arguments: a pointer to a ProtocolCallContext object, the principal ID of the recipient client, and a UserMessageDataHolder object holding a pointer to a UserMessage (or TextMessage or BinaryMessage) object. (See Code 4.10.)

Use the MessagingClient::SendChat function to send a message to all the clients that have joined a particular matchmaking session. This function takes the following arguments: a pointer to a ProtocolCallContext object, the matchmaking session ID of the recipient client, and a UserMessageDataHolder object holding a pointer to a UserMessage (or TextMessage or BinaryMessage) object.

Comments

The asynchronous call returns success when the message reaches the game server. It is not possible to tell whether the message actually reached the recipient from the result of the asynchronous call. If a message reaches the game server, it is guaranteed to reach the recipient, providing the recipient is connected to the game server.

Note

The MessageClient::SendChat function supports up to 32 connected clients. Contact Nintendo if you want to use this function with more than 32 clients.

Code 4.10. Sample Code for Sending a Text Message

void SendInstantMessage(MessagingClient *pMessagingClient, PrincipalID target, const String& message)
{
    TextMessage *pTextMessage = qNew TextMessage();
    UserMessageDataHolder oDataHolder = pTextMessage;

    // Set the message.
    pTextMessage->SetTextBody(message);

    ProtocolCallContext oContext;
    if(pMessagingClient->SendInstant(&oContext, pid, oDataHolder))
    {
        oContext.Wait();
        if(oContext.GetState() != CallContext::CallSuccess)
        {
            // Error handling.
        }
    }
    else
    {
        // Error handling.
    }
}

4.22.2. Handling Message Notifications

For a client to receive messages, the MessagingClient::RegisterMessagingNotificationHandler function must register a MessagingNotificationHandler with the client process after the MessagingClient::Bind function is run. Each time the client receives a notification message after the handler is registered, the message is sent to the handler and the DeliverInstantMessage callback is invoked. To customize how messages are processed, make MessagingNotificationHandler into a subclass and re-implement the system callback. (For more information, see Code 4.11.)

In the DeliverInstantMessage callback, use the DataHolder::Get function to get the stored message. Use DynamicCast to determine whether the message is an instance of the UserMessage, TextMessage, or BinaryMessage concrete class.

For example, use the TextMessage::DynamicCast function to tell if the message can be dynamically cast to a TextMessage object. Similarly, use the BinaryMessage::DynamicCast function to tell if it is a BinaryMessage object.

The following example shows a messaging notification handler that determines the type of the message object.

Code 4.11 Making MessagingNotificationHandler a Subclass

class MyMessagingNotificationHandler: public MessagingNotificationHandler
{
public:
// Overridden from MessagingNotificationHandler.
void DeliverInstantMessage(const DataHolder& hMsg)
{
    if (TextMessage::DynamicCast(hMsg.Get()))
    {
        // If TextMessage::DynamicCast succeeds, a TextMessage object is received.
        TextMessage* pTextMsg = static_cast<TextMessage*>( hMsg.Get() );
        NN_LOG("from:%u message:%ls \n", pTextMsg->GetSenderID() ,pTextMsg->GetTextBody().CStr());
    }
    else if (BinaryMessage::DynamicCast(hMsg.Get()))
    {
        // If BinaryMessage::DynamicCast succeeds, a BinaryMessage object has been received.
        BinaryMessage* pBinaryMsg = static_cast<BinaryMessage*>( hMsg.Get() );
        NN_LOG("from:%u size:%u \n", pBinaryMsg->GetSenderID() ,pBinaryMsg->GetBufferSize());
    }
};

4.23. Using the Host Migration Extension Feature

When the current host of a P2P communication session leaves the session, NetZ automatically migrates the host to another participant. Matchmaking sessions record the host information for the P2P communication, and this is cleared when the host leaves the matchmaking session. Host information is required to join the P2P session. Update it as needed. If the host migration extension is being used when the P2P session host is migrated, the game server is notified of that fact, and the information for the matchmaking session P2P communication host is updated. When using the host migration extension feature, the MatchMakingClient::UpdateSessionHost function is called appropriately for the corresponding matchmaking session when the session host is migrated. The following procedure shows how to use the host migration extension package.

  1. Write #use <NetZ/src/Core/HostMigration/HostMigrationExt.ddl> to the .ddl file.
  2. Run the HostMigrationExtension::Register function after NetZ objects are generated.
  3. Generate HostMigrationCallback by using the generated MatchmakeExtensionClient and the callback function that is called when host migration occurred — normally either the MatchmakingClient::StaticUpdateSessionHost or the MatchmakingClient::StaticUpdateSessionHostWithOwner function.
  4. Register the ID of the gathering that is joined by using the HostMigrationCallback::Register function.

The flowchart in Figure 4.2 shows the sequence of events that starts when a matchmaking session is registered and ends when the host is migrated. If the P2P session ends normally, leave the matchmaking session immediately.

When a client that is not the host is isolated from a P2P session, a host migration occurs with the approval of at least one client that is not the local host. However, if there are only two people in a session and the stations are lost because of an abnormal state by a timeout or other event occurring, since it is unknown whether that client should be promoted to the host, the call to the MatchMakingClient::UpdateSessionHost function is not made. This state is called isolation and is determined by the HostMigrationCallback::SessionHostIsOrphan function. If a client is determined to be isolated, have it leave the matchmaking session. If there are only two players in a session when one terminal leaves normally (by using the NetZ::Terminate function without specifying the NetZ::SetTerminateImmediately function), an isolated state is not determined. If the host leaves, host migration occurs.

The game can continue because host migration takes place even when clients become isolated, but other clients cannot join the P2P session because a matchmaking session in which the host can join from the outside does not exist. Register a new matchmaking session so that other clients can join. Also, you must destroy the HostMigrationCallback object, create a new HostMigrationCallback object, and register a new ID.

Comments

If the host is migrated and the game server is not notified of the new host, the MatchMakingClient::GetSessionURLs function returns the URL of the previous host (prior to the migration). You must use the host migration extension feature to allow other clients to join the P2P session even after the host has left.

Comments

If your ROM uses both Internet and local communication modes and uses the host migration extension feature when in Internet communication mode, you can skip calling the HostMigrationExtension::Register function by calling the HostMigrationExtension::Disable function.

_images/Fig_Matchmake_Flow.png

Figure 4.2. Processing Flow From Matchmaking Session Registration to Host Migration

4.24 Using the MatchmakeReferee Feature

The MatchmakeReferee feature records results fairly by summarizing match reports sent by clients and checking them all together. This record is called personal statistics.

Personal statistics include the following.

  • Primary associated NEX unique ID (the principal ID if NEX unique IDs are not being used).
  • Category.
  • Last used principal ID.
  • Number of disconnects in the most recent 100 matches.
  • Number of violations in the most recent 100 matches.
  • Number of report mismatches in the most recent 100 matches.
  • Number of wins in the most recent 100 matches.
  • Number of losses in the most recent 100 matches.
  • Number of draws in the most recent 100 matches.
  • Total number of disconnects until now.
  • Total number of violations until now.
  • Total number of report mismatches until now.
  • Total number of wins until now.
  • Total number of losses until now.
  • Total number of draws until now.
  • Rating value.

Items other than report mismatches are updated based on the content of reports sent from clients.

4.24.1. Personal Statistics Recording Units

The default recording unit is by principal ID, but statistics can be recorded in finer units by registering a NEX unique ID as a primary associated NEX unique ID.

For more information, see Section 11.2 Using NEX Unique IDs With the MatchmakeReferee Feature.

The default functionality if a NEX unique ID is not used is to use the principal ID internally as the primary associated NEX unique ID.

4.24.2. Overall Flow of the MatchmakeReferee Feature

  1. Load the primary associated NEX unique ID from save data.
  2. Log in with the NgsFacade::Login function.
  3. If there is no primary associated NEX unique ID, get one with the UtilityClient::AcquireNexUniqueIdWithPassword function.
  4. Call the UtilityClient::AssociateNexUniqueIdWithMyPrincipalId function to declare the primary associated NEX unique ID to be used.
  5. Call the MatchmakeRefereeClient::GetOrCreatePersonalStats function to get or create personal statistics.
  6. Call the MatchmakeRefereeClient::GetNotSummarizedRound function as needed to check whether there is a round that is not summarized yet.
  7. Perform matchmaking and participate in a matchmaking session, and establish a P2P session.
  8. The P2P session host calls the MatchmakeRefereeClient::StartRound function. NotificationEvents::RoundStarted notifications are sent to round participants, who can get the personal statistics of opponents by calling the MatchmakeRefereeClient::GetStats function as necessary.
  9. To withdraw during the round, call the MatchmakeRefereeClient::EndRoundWithoutReport function.
  10. When the round ends, each user calls the MatchmakeRefereeClient::EndRound function to report the round results for all users as a qVector< MatchmakeRefereePersonalRoundResult >.
  11. Wait for the notification that summarization has completed (NotificationEvents::RoundSummarized) and display the round results.

Comments

If personal statistics are being managed in units of principal IDs, steps 1, 3, and 4 are not needed.

4.24.3. Report Summarizing on the Server

Summarizing the report on the server is done after the reports from all round participants are received (including empty reports from calls to MatchmakeRefereeClient::EndRoundWithoutReport), or one minute after the first report is received (not including empty reports from calls to MatchmakeRefereeClient::EndRoundWithoutReport).

The MatchmakeRefereeClient::EndRoundWithoutReport function is called to allow summarizing to start without having to wait for the one-minute timeout. The feature still works even if this function is not called, but processing to summarize starts late. Make sure to call it in any situation where you cannot call MatchmakeRefereeClient::EndRound, such as when withdrawing during the round.

In the report summarizing process on the server, the reports sent (qVector< MatchmakeRefereePersonalRoundResult >) are checked to verify that they match with reports sent by other round participants. The concordance check of qVector <MatchmakeRefereePersonalRoundResult> is conducted between those with matching MatchmakeRefereePersonalRoundResult PIDs. The order of MatchmakeRefereePersonalRoundResult within qVector does not need to match between the reports sent by each user. If the data from more than half of the reports matches, that data is used as the final result. This process is called normalization.

The normalized report is held on the server for one hour. You can get the normalized report by calling the MatchmakeRefereeClient::GetRound function. The personal statistics linked to the primary associated NEX unique ID are updated based on the normalized report. The personal statistics are persistent data. You can get the personal statistics by using the MatchmakeRefereeClient::GetStats function. For more information about personal statistics, see MatchmakeRefereeStats.

In the following cases, the round is considered invalid and the personal statistics are not updated.

4.25. Error Handling

4.25.1. Errors During Function Calls

Asynchronous functions that communicate with the game server could return false for the following reasons.

  1. A CallContext object was passed as an argument while it was being used by another asynchronous process.
  2. The ServiceClient::Bind function has not been run.
  3. Data failed to be sent to the game server (such as when a connection with the game server was lost).

All asynchronous functions check these reasons in the listed order. Although (1) and (2) are program errors, (3) is caused by the network state. You must log in to the game server again to restore communication with it from this state. For this reason, display the error message "A communication error has occurred" and then shut down communication. For more information, see Code 4.12 Sample Error Handling.

4.25.2. Asynchronous Processing Errors

You can get asynchronous processing results with the CallContext::GetOutcome function. The API Reference Manual describes errors that must be handled by the application for each function. If an undocumented error occurs, use the following code to get the network error code with the ErrorCodeConverter::ConvertToNetworkErrorCode function, pass the error code to the error/EULA applet, and then shut down communication (Code 4.12).

Code 4.12. Sample Error Handling

MatchmakeExtensionClient client;
ProtocolCallContext context;

// Error handling for function calls.
if(!client.JoinMatchmakeSession(&context, gid, _T("join message")))
{

    // A CallContext was passed in while it was still being processed.
    NN_ASSERT(context.GetState() != CallContext::CallInProgress);

    // Bind has not been run.
    NN_ASSERT(client.GetCredentials() != NULL);



    // Other, such as the network is not connected.
    // Display the message "A communication error occurred." (The error code is unnecessary.)
    // Log out and shut down.
}

// Error handling for asynchronous processing.
context.Wait(); //Block and wait here.


if(context.GetState() != CallContext::CallSuccess)
// Note: To cancel the context, you must also make a comparison with CallContext::CallCancelled.
{
    qResult result = context.GetOutcome();

    // Errors that must be handled by the application.
    if(result == QERROR(RendezVous, SessionVoid))
    {
        // There is no matchmaking session.
    }
    else if(result == QERROR(RendezVous, SessionFull))
    {
        // The matchmaking session is full.
    }
    else
    {
        u32 code = ErrorCodeConverter::ConvertToNetworkErrorCode(result);
        // Start the error/EULA applet.
        // Log out and shut down.
    }
}

CONFIDENTIAL