//-----------------------------------------------------------------------------
//
// Sample Name: ChatPeer Sample
//
// Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
Description
===========
ChatPeer is similar in form to SimplePeer. Once a player hosts or connects
to a session, the players can chat with either other by passing text
strings.
Path
====
Source: DXSDK\Samples\Multimedia\DirectPlay\ChatPeer
Executable: DXSDK\Samples\Multimedia\DirectPlay\Bin
User's Guide
============
Refer to User's Guide section of the SimplePeer sample.
Programming Notes
=================
The ChatPeer sample is very similar in form to the SimplePeer sample. For
detailed programming notes on the basics this sample, refer to Programming
Notes section of the SimplePeer sample.
The ChatPeer differs by letting clients send text strings to all players
connected to the session.
* The "Send" button is pressed. See SendChatMessage().
1. Retrieves the text string from the dialog.
2. Fills a app defined struct, GAMEMSG_CHAT. This struct has
a message type ID as the first BYTE. This lets our app
figure out what type of app message they received, however
ChatPeer only uses one app defined message. See StagedPeer
for a more complex example of this process.
3. Fills out a DPN_BUFFER_DESC struct using the GAMEMSG_CHAT buffer.
4. Calls IDirectPlay8Peer::SendTo() with the DPN_BUFFER_DESC. It passes
DPNID_ALL_PLAYERS_GROUP so this message goes to everyone.
* Handle DirectPlay system messages. See DirectPlayMessageHandler()
The ChatPeer handles the typical messages as described in the
SimplePeer programming notes, and in addition:
- Upon DPN_MSGID_RECEIVE message:
1. It casts pReceiveMsg->pReceiveData into a generic app defined
structure, GAMEMSG_GENERIC. This helps to figure out what structure
is really contained in pReceiveMsg->pReceiveData. For this simple
example, if the ID is GAME_MSGID_CHAT it casts the buffer to a
GAMEMSG_CHAT*.
2. It then creates a new APP_QUEUED_DATA struct which contains a pointer
to the GAMEMSG_CHAT buffer, and the a DirectPlay handle linked to the
GAMEMSG_CHAT buffer.
3. We then post a user defined message, WM_APP_CHAT, to the dialog thread
with the lParam equal to a pointer to the APP_QUEUED_DATA struct and
the wParam equal to the DPNID of the player who sent us the buffer.
We post a message since this lets us return from the DirectPlay message
handler quickly. In a complex game if the handler threads take too
long its possible that a backlog of network data may arise.
4. We return from DirectPlayMessageHandler() with the result code
of DPNSUCCESS_PENDING. This error code tells DirectPlay that the buffer
we got in the DPN_MSGID_RECEIVE message is still in use by our app.
This allows us to not to have to copy the buffer, but instead pass a
pointer of it off to a worker thread. This simple sample just uses
the main dialog thread to process queued data. For a more complex
example of this process see the DataRelay sample.
* Upon receiving WM_APP_CHAT in the message loop
This is posted to the message loop by one DirectPlay message handler threads
whenever we receive a chat message. See above for more detail. Here's what
happens:
1. Cast the wParam to a DPNID. This is the player that sent the message.
2. Calls IDirectPlay8Peer::GetPlayerContext(). This retrieves a user
specified pointer (which we cast to a APP_PLAYER_INFO*) associated with
this player. See the SimplePeer programming notes for more info on how
this is setup. Also, note that since player can be deleted at any time,
we need to use ref counting to make sure this player context struct isn't
deleted while we are still using it.
3. Cast the lParam into a APP_QUEUED_DATA*. This tells us the buffer, and the DirectPlay
handle associated with that buffer.
4. Process the buffer by adding it's text string to the dialog.
5. Release the APP_PLAYER_INFO* since we are done using it.
6. Now DirectPlay can free the receive buffer since we are done with it.
So return the buffer to DirectPlay by calling IDirectPlay8Peer::ReturnBuffer,
passing in the DirectPlay buffer handle.
7. Deletes the APP_QUEUED_DATA from the heap