11.2. Migrating From NetZ in NEX to PiaSession

This chapter describes the information to consider when transitioning an application developed using NetZ to PiaSession.

Matchmaking

Replace calls to the NEX matchmaking API with calls to the PiaSession session API. For example, replace calls to the nex::MatchmakeExtensionClient::AutoMatchmake() function with calls to the pia::session::Session::JoinRandomSessionAsync() function. If you make calls to the NEX matchmaking API directly from your application, however, you do not need to make any changes.

Sending Data

The API functions in Pia that correspond to those in DirectStream in NetZ are in transport::UnreliableProtocol and transport::ReliableProtocol. Error handling for the send functions differs in the following ways.

Pia is designed so that during initialization, maximum values are taken for the memory used and the number of buffers. As a result, when sends are executed at a high frequency and the buffers within Pia are depleted, the send functions are set to return a ResultBufferIsFull error. However, buffer depletion is temporary. If buffer depletion occurs, buffer elements are processed in order and buffer space becomes available if you continue to periodically call the pia::common::Scheduler::Dispatch() function.

When using unreliable sends (sends that use the transport::UnreliableProtocol class), no particular handling is needed. The ResultBufferIsFull error can be ignored, and you can handle it the same way you would handle packet loss.

When the ResultBufferIsFull error is returned when using reliable sends (sends that use the transport::ReliableProtocol class), the application maintains any data that has failed to be sent. You must handle this error by resending the data at the next opportunity.

 

Code 11-1. Sending Data in Pia
nn::Result r = pReliableProtocol->Send(destStationId, pData, dataSize);
if(r.IsSuccess())
{
    // Sending was successful. Advance the pointer to the next data.
    pData = getNextData(pData);
}
else if(r==nn::pia::ResultBufferIsFull())
{
    // When you attempt to run the Send() function more frequently than the send buffer can keep up with,
    // the ReliableProtocol::Send() function fails. The data that failed in the Send() function for this reason must be resent.
    // The application is responsible for this. As a result, in this case, pData is not changed,
    // and an attempt is made to send again at the next opportunity.
}
else
{
    PIA_TRACE_RESULT(r);
    PIA_ASSERTMSG(false, "Programming error.");
}

Receiving Data

When using the DirectStream class in NetZ, the application uses the polling method and calls the GetReceivedData() function. Pia also receives data with the polling method. For example, transport::ReliableProtocol and transport::UnreliableProtocol have a Receive() function that can be called periodically. When data cannot be obtained because the receive data has not arrived yet, the ResultNoData error is returned. You must handle that error appropriately.

 

Code 11-2. Receiving Data in Pia
// Receiving arrived data.
nn::Result r = pUnreliableProtocol->Receive(&srcId, reinterpret_cast<bit8*>(buf), sizeof(buf), &receivedSize);
if(r.IsSuccess())
{
    // The data has been successfully received. The sender of the data and the data content will be printed to the screen.
    PIA_CACHED_PRINTF("Received from 0x%016llX. Data(%d bytes): [%s]\n", srcId, receivedSize, buf);
}
else if(r==nn::pia::ResultNoData())
{
    // The data might not have arrived yet. In that case, do nothing.
}
else
{
    PIA_TRACE_RESULT(r);
    PIA_ASSERTMSG(false, "Programming error.");
}

Dispatch Function

To use PiaSession, you must call the dispatch function (pia::common::Scheduler::Dispatch()) at least once every game frame. When using Internet communication, you must call the NEX dispatch function (nex::Scheduler::Dispatch()) for the NEX server services.

Starting and Stopping a NAT Session

The pia::inet::NexFacade class handles NAT traversal when using Internet communication in Pia. The pia::inet::NexFacade class includes features that are equivalent to those of nex::NATTraversalClient and nex::ConnectivityManager in NetZ. However, you must not use the nex::NATTraversalClient object in your application when using Pia because doing so creates competing behaviors. For the same reason, do not call the StartNATSession() and StopNATSession() functions in the nex::ConnectivityManager class.

 

Code 11-3. Differences Between Starting and Stopping NAT Sessions
// NetZ
s_pNatTraversalClient = qNew nn::nex::NATTraversalClient();
s_pNatTraversalClient->Bind(s_pNgsFacade->GetCredentials());
nn::nex::ConnectivityManager::GetInstance()->StartNATSession(&callContext);
    ...
nn::nex::ConnectivityManager::GetInstance()->StopNATSession();
s_pNatTraversalClient->Unbind();
qDelete s_pNatTraversalClient;

// Pia
// This happens automatically when calls to the session creation and join functions are made, so you do not need to call it from the application.

Station Identification Tokens

Pia can also use tokens to identify stations. In NetZ, the token was configured as a string in nex::String. In Pia, it is configured as a 32-byte u8-type array.

Code 11-4. Configuring Identification Tokens
// Configure during session startup.
nn::pia::session::Session::StartupSetting startupSetting;

// Setting for the identification token representing the local station.
nn::pia::transport::Station::IdentificationToken localToken;
// Assume that LOCAL_TOKEN_DATA is the leading address of the data string for the identification token IDENTIFICATION_TOKEN_MAX_DATA_SIZE [byte].
::std::memcpy( localToken.data, LOCAL_TOKEN_DATA, nn::pia::transport::Station::IDENTIFICATION_TOKEN_MAX_DATA_SIZE );
startupSetting.pToken = &localToken;

result = nn::pia::session::Session::GetInstance()->Startup(startupSetting);
if ( result.IsFailure() )
{
    // Error handling.
}

Session Events

NetZ included the following session events.

  • None
    Occurs when a station joins the session.

  • Participated
    Occurs when a station joins the session.

  • Left
    Occurs when a station leaves a session.

Pia includes the following session events.

  • EVENT_JOIN
    Occurs when a station joins the session.

  • EVENT_LEAVE
    Occurs when a station leaves a session.

  • EVENT_SESSION_HOST_CHANGED
    Occurs when host migration occurs (only when host migration is enabled).

  • EVENT_HOST_MIGRATION_FAILED
    Occurs when host migration fails (only when host migration is enabled).

  • EVENT_SET_SESSION_SYSTEM_PASSWORD
  • EVENT_CLEAR_SESSION_SYSTEM_PASSWORD
    Occurs when the system password for a session is cleared (if a password has been set). For more information, see 6.17. Advanced Features - Session Password Settings.

There are also other events that occur when the joint session feature is used. For more information, see 6.12. Advanced Features - Joint Session Feature.

To differentiate between the creation of a session and stations joining the session, compare the station ID that triggered the event and the local station ID.

Adjusting the Memory Size Assigned to Pia

Pia differs from NEX in that the memory is not dynamically allocated during communication. Pia is designed to have the amount of memory established during initialization. The description for adjusting the memory size assigned to Pia is included in 5. PiaTransport Guide.

Handling Errors

Error handling in Pia differs from that of NEX. In places where the NEX API has been replaced with Pia API, you must revise the error handling format of Pia. For more information about error handling for Pia, see 1.8. Error Handling.

Initialize the socket library.

The nn::socket::Initialize() function has a parameter for specifying the number of sessions. Set this function to the number of sessions plus three because the Pia library calls sockets from three threads. For more information, see 4. PiaInet Guide.

Other

When migrating from NetZ to PiaSession, you must make changes to the following API functions. However, the features involved do not differ greatly from NetZ to PiaSession. You can get support in PiaSession with a minor revision along the lines of changing the name of the function that is called.

  • The API for setting the callback to determine session joining approval or denial and the callback for session state updates
  • The API function for getting the synchronization clock
Code 11-5. Registering a Callback for Determining Approval to Join Session
nn::pia::session::Session::GetInstance()->RegisterJoiningApprovalCallback(callback);
Code 11-6. Getting the Synchronization Clock
s64 now = nn::pia::session::Session::GetInstance()->GetSyncClockTime();