Initial commit: ROW Client source code
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>
This commit is contained in:
126
Library/dxx8/samples/Multimedia/DirectPlay/DataRelay/readme.txt
Normal file
126
Library/dxx8/samples/Multimedia/DirectPlay/DataRelay/readme.txt
Normal file
@@ -0,0 +1,126 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Sample Name: DataRelay Sample
|
||||
//
|
||||
// Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
The DataRelay is similar to SimplePeer but differs by sending a single
|
||||
target (or everyone) a packet of data with options specified in the
|
||||
dialog's UI. It uses a worker thread to process received data, and
|
||||
uses the ReturnBuffer() API so that no copying of the received buffers
|
||||
is done.
|
||||
|
||||
Path
|
||||
====
|
||||
Source: DXSDK\Samples\Multimedia\DirectPlay\DataRelay
|
||||
|
||||
Executable: DXSDK\Samples\Multimedia\DirectPlay\Bin
|
||||
|
||||
User's Guide
|
||||
============
|
||||
Host or connect to a session in the same manner as explained in SimplePeer.
|
||||
When the main dialog appears select the target, size, rate, and timeout values.
|
||||
Then click "Push to Send". This will send a packet of data to the target as
|
||||
the rate specified with the specified size. Use the "Connection Info" dropdown
|
||||
to specify a target to gather connection info on periodically.
|
||||
|
||||
Programming Notes
|
||||
=================
|
||||
The DataRelay 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 DataRelay differs by sending a single target (or everyone) a packet of
|
||||
data with options specified in the dialog's UI.
|
||||
|
||||
When the "Push to Send" button is clicked, then win32 timer is created
|
||||
that goes off every number of ms according to the UI.
|
||||
|
||||
* Upon the WM_TIMER labeled TIMERID_NETWORK, it calls SendNetworkData().
|
||||
1. It creates a app defined struct, GAMEMSG_DATA_xxx on the heap.
|
||||
The struct derives from GAMEMSG_GENERIC. GAMEMSG_GENERIC contains a
|
||||
packet type field so that the reciever and identify this app defined
|
||||
packet, and it contains a packet ID field. This field is sequential
|
||||
and is displayed to the user whenever a packet is received. The struct
|
||||
is created on the heap, since will use the DPNSEND_NOCOPY when calling
|
||||
SendTo() below. The struct is filled with random data, however a real
|
||||
app would typically send player and world state data here.
|
||||
2. It then creates a GAMEMSG_DATA_NODE which is then handed off to the
|
||||
app worker thread. That thread will process the node, and
|
||||
then update the UI to show that a packet was sent. It is handed off
|
||||
by adding the node to a linked list. Since the worker thread also
|
||||
accesses the linked list, we enter a critical section before adding the
|
||||
node and leave it afterward.
|
||||
3. A DPN_BUFFER_DESC is then filled out passing in a pointer to the
|
||||
app defined struct created above.
|
||||
4. IDirectPlay8Peer::SendTo is called passing in the DPN_BUFFER_DESC, thereby
|
||||
sending the app defined struct, GAMEMSG_DATA_xxx. We call SendTo with
|
||||
the flags DPNSEND_NOLOOPBACK | DPNSEND_NOCOPY. DPNSEND_NOLOOPBACK tells
|
||||
DirectPlay to not to send the buffer to us, and DPNSEND_NOCOPY means that
|
||||
DirectPlay should not copy the buffer. When the DPNSEND_NOCOPY is used,
|
||||
the app itself owns the buffer, and the buffer must be on the heap.
|
||||
When the DPN_MSGID_SEND_COMPLETE comes in, we will delete the buffer.
|
||||
5. The event, g_hDPDataAvailEvent, is set telling the worker thread that
|
||||
there is data (a message to say that a packet was sent), is ready to
|
||||
be processed now.
|
||||
|
||||
* Handle DirectPlay system messages. See DirectPlayMessageHandler()
|
||||
The DataRelay handles the typical messages as described in the
|
||||
SimplePeer programming notes, and in addition:
|
||||
|
||||
- Upon DPN_MSGID_RECEIVE
|
||||
1. It casts the pReceiveMsg->pReceiveData to a GAMEMSG_GENERIC*.
|
||||
2. It then switches off the GAMEMSG_GENERIC's dwType.
|
||||
3. If its a GAME_MSGID_GAMEPACKET, then it creates and fills out
|
||||
a GAMEMSG_DATA_NODE. This node is then handed to a worker thread
|
||||
so it can be processed outside of the DirectPlay message handler.
|
||||
This is important since it keeps the DirectPlay threads working at
|
||||
full speed.
|
||||
4. After the node is added to the linked list using a critical section
|
||||
to lock, it returns DPNSUCCESS_PENDING. This is important since
|
||||
it tells DirectPlay that ownership of the buffer
|
||||
has been transferred to the application, and so DirectPlay will
|
||||
neither free nor modify it until ownership is returned
|
||||
to DirectPlay through the ReturnBuffer() call.
|
||||
|
||||
- Upon DPN_MSGID_SEND_COMPLETE
|
||||
1. It checks the pSendCompleteMsg->hResultCode for DPNERR_TIMEDOUT.
|
||||
2. If this occurs then it creates a new GAMEMSG_DATA_NODE with dwType
|
||||
set to DATA_TYPE_NETPACKET_TIMEOUT. This will is passed to the
|
||||
worker thread. The worker thread will process this node, and
|
||||
post a message to the dialog saying that the message timed out.
|
||||
A realistic application would want to take the appropriate steps here,
|
||||
such as resending new data or other measures.
|
||||
3. It deletes the buffer from the heap since we specified, DPNSEND_NOCOPY,
|
||||
so the buffer on the heap belows the app and it must clean it up.
|
||||
|
||||
* The worker thread. See ProcessNetDataProc()
|
||||
- Upon the g_hDPDataAvailEvent
|
||||
1. When the event is signaled, then new data can be found in the
|
||||
linked list, g_DataHead. So it calls ProcessData().
|
||||
2. ProcessData() first enters the critical section, g_csDataList, so
|
||||
that the other threads don't modify the linked list while it is
|
||||
processing data. It leaves this critical section at the end of the
|
||||
loop. Typically better locking mechanisms would be used so that the
|
||||
other threads (as well as the DirectPlay message handler threads)
|
||||
aren't blocked while data is processed on this thread.
|
||||
3. It runs through the linked list, processing each node. For this
|
||||
simple sample all it does is posting a message to the dialog thread,
|
||||
containing a string for the dialog to display.
|
||||
4. After it is done processing the node, it calls
|
||||
IDirectPlay8Peer::ReturnBuffer() so that DirectPlay can free
|
||||
buffer that it passed us in DPN_MSGID_RECEIVE.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user