Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
96 lines
4.9 KiB
Plaintext
96 lines
4.9 KiB
Plaintext
//-----------------------------------------------------------------------------
|
|
//
|
|
// 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
|
|
|
|
|
|
|