Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
99 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

  Contents

 Introduction
 Let's get started
 Implementation
 Setting up
 the Connection

 Message
 Management

 Putting it
 Together


 Printable version

 


Message Management

Now that we have a player, we need to know how to send and receive messages. I will talk about sending messages first.

Sending Messages

There is only one way to send a message and that is through the Send function. (Actually there is another if you use a lobby). If you remember, sending a message requires the id of the sender and the receiver. Good thing you have saved the local player id in a local player struct and all the players' ids in a global player list. So call the function as follows:

lpdp->Send(idFrom, idTo, dwFlags, lpData, dwDataSize);

The idFrom is the id of the local player. This must be set to a locally created player only (we don't want to impersonate another player, do we?) which in most cases is only one. The idTo is the receiver's id. Use DPID_SERVERPLAYER to send to the server only and DPID_ALLPLAYERS to send to everybody (except yourself). Note you cannot send a message to yourself. If you want to direct the message to a specific player, use the player list. You do not have to use a player list in a chat; instead you can add everything to a listbox. But later in the game, a list of players comes handy.

The flag parameter is how should the message be sent. The default is 0, which means non-guaranteed. The other options are DPSEND_GUARANTTED, DPSEND_ENCRYPTED and DPSEND_SIGNED. Sending a guaranteed message can take more than 3 times longer than a non-guaranteed one so only use guaranteed sending for important messages (like text). The signed and encrypted messages require a secure server, which we did not setup. Also any message received is guaranteed to be free of corruption (DirectPlay performs integrity checks on them).

Something to note: If you create a session that specifies no message id, their message idFrom will make no sense and the receiver will receive a message from DPID_UNKNOWN. Why anyone would want to disable message id is beyond me.

The last two parameters are a pointer to the data to send and the size of that block. Note that DirectPlay has no upper limit of the size you can send. DirectPlay will break large messages into smaller packets and reassemble them at the other end. Beware when sending non-guaranteed messages too; if one packet is lost, the whole message is discarded.

Since we are doing a chat program, I will show an example of sending a chat message

Popup : DP_Send_String_Mesg

We first define the types of messages we can have. Since this is a chat program, there can only be one type, which I set to DP_MSG_CHATSTRING. You may add others and set the type so you can reuse the string sending function for different things. That is why the string message struct has a type to differentiate the string contents. The send function basically allocates space and sends the function to the desired player. Note the local_player_id is stored somewhere globally, or you can set it to pass another variable to set the local_player_flag. Do check the errors returned especially with allocation routines.

Receiving Messages

Receiving messages requires slightly more work than sending. There are two types of messages we can receive – a player message and a system message. A system message is sent when a change in the session state occurs. The system messages we trapped in this chat are:

DPSYS_SESSIONLOSTthe session was lost
DPSYS_HOSTthe current host has left and you are the new host
DPSYS_CREATEPLAYERORGROUPa new player has join
DPSYS_DESTROYPLAYERORGROUPa player has left

Some of those messages are only sent if certain flags are specified when then host creates the session. Consult the MSDN.

The Receive function has similar syntax to the Send function. The only different thing worth mentioning is the third parameter. Instead of the sending parameter, it is a receiving parameter. Set that to 0 for the default value, meaning extract the first message and delete it from the queue.

The whole difficult part about the receiving is that we need to cast the message to DPMSG_GENERIC and it gets messy there. So I give you the function and explain it below.

Popup : Receive_Mesg

First we check if there are any messages in the loop. If not, we break out of this function. We then keep trying to receive the message in the buffer by allocating the new buffer. When the return value is not DPERR_BUFFERTOOSMALL, it means either we have received the message or another serious error has occurred. So we check if the hresult is successful before determining whether it is a system or application message, by which we call the appropriate functions. System messages come from DPID_SYSMSG, which is a reserved value in DirectPlay.

The 2 functions should be implemented as follows:

Popup : Message Handlers

The two functions are very similar. To get the actual message, we need to cast the message to the appropriate type before extracting the individual components. Even if the application message comes through, we need to cast it get the data within. The dwType parameter we defined in the chat string struct above enables us to differentiate the different messages the application defines. Although the chat requires only one message, which is the chat message, there is definitely a need for more messages types the application should handle. Every new message type you define should include a dwType parameter so the application can differentiate the messages.


Next : Putting It Together