Using Player Context Values

DirectPlay

 
Microsoft DirectX 9.0 SDK Update (Summer 2003)

Using Player Context Values


Most applications will want to associate some data with each player. However, when you receive a message that is associated to a player, you need some way to access that data quickly. Player context values are designed to provide you with an efficient way to access your player data.

Note  Only the IDirectPlay8Peer and IDirectPlay8Server interfaces use player context values. They are not needed for the IDirectPlay8Client interface because clients use this interface to communicate only with the server, not other clients.

Defining a Player Context Value

To user player context values, you need to have a block of data on your system for each player, typically in the form of a structure. A player context value is normally an index into an array of pointers to the various players' data blocks. When you receive a message from a player, there is no need for time-consuming operations such as searching for the player's identifier (ID) in a table. The index contained in the player context value allows you to quickly obtain the necessary pointer.

You define a player context value when you handle the DPN_MSGID_CREATE_PLAYER message that notifies you that a player has been added to the game. Host's can also define a player context value when they handle the DPN_MSGID_INDICATE_CONNECT message. That player context value will be set in the subsequent DPN_MSGID_CREATE_PLAYER message. When the host processes that message, it has the option of changing the player context value. To create a player context value:

  • Allocate a structure to hold the player's data.
  • Add the structure pointer to your player data array.
  • Assign the index of that pointer to the pvPlayerContext member of the message's DPN_MSGID_CREATE_PLAYER structure.

Microsoft® DirectPlay® does not specify how you should obtain the data to populate the structure. Each game is responsible for handling that issue in its own way.

Note  The only place you can define a player context value is in a DPN_MSGID_CREATE_PLAYER or DPN_MSGID_INDICATE_CONNECT message handler. When the DPN_MSGID_CREATE_PLAYER message handler returns, the player context value is set. For each subsequent message associated with that player, the player context value will be the same value that was set by the DPN_MSGID_CREATE_PLAYER message handler. You can modify the contents of the associated data structure, but you cannot change the player context value itself.

Managing Player Context Data

While player context values are fairly straightforward to handle, there are a couple of issues that you need to be careful with.

The player context value provides you with a quick way to obtain a valid memory address that will presumably be accessed each time a message arrives. However, you must be careful that different parts of your application do not access the data at the same time. DirectPlay serializes messages associated with a particular player, which guarantees that you will never be handling two messages from the same player at the same time. As long as you only access the data structure from your callback message handler, you can safely access the structure. However, most applications will need to access player data outside the message handler.

If your application accesses the data outside the callback message handler, you must prevent concurrent access by providing some sort of global mechanism to lock the structure. Even if your application does not require such locking in the early stages of development, you should assume that locking will eventually be required, and build it in from the beginning. If your player context values that are indexes into an array, you should also make sure that you read and update that array safely.

Don't deallocate a player's data structure prematurely. When a player leaves the game, you will normally want to deallocate their data structure and free the associated memory. However, be careful about deallocating the structure as soon as you receive a DPN_MSGID_DESTROY_PLAYER message. If your application accesses that structure outside the callback message handler, that data may still be in use when the message arrives. If you deallocate the structure as soon as the message arrives, you may cause other parts of your application to fail.

To avoid prematurely deallocating the structure, you should not only provide an application-level locking mechanism, you should also implement some sort of reference counting. Increment this reference count when you create the structure, and every time you use it. Decrement the reference count every time you have finished with the structure, including in your DPN_MSGID_DESTROY_PLAYER message handler. As long as the reference count is nonzero, some part of your application is accessing the structure. Do not deallocate the structure until the reference count drops to zero.


© 2003 Microsoft Corporation. All rights reserved.