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:
2025-11-29 16:24:34 +09:00
commit e067522598
5135 changed files with 1745744 additions and 0 deletions

View File

@@ -0,0 +1,845 @@
//----------------------------------------------------------------------------
// File: dplay8client.cpp
//
// Desc: see main.cpp
//
// Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
//-----------------------------------------------------------------------------
#include <windows.h>
#include <d3dx.h>
#include <process.h>
#include <tchar.h>
#include <assert.h>
#include <dxerr8.h>
#include <stdio.h>
#include <dplay8.h>
#include <dpaddr.h>
#include "DummyConnector.h"
#include "StressMazeGUID.h"
#include "DXUtil.h"
#include "MazeApp.h"
#include "DPlay8Client.h"
#define DPMAZESERVER_PORT 2309
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
CDPlay8Client::CDPlay8Client()
{
m_dwNumSessions = 0;
m_wActiveThreadCount = 0;
m_wMaxThreadCount = 0;
m_fAvgThreadCount = 0;
m_fAvgThreadTime = 0;
m_fMaxThreadTime = 0;
m_pClient = NULL;
m_pDPlay = NULL;
m_dpnhEnum = NULL;
m_bSessionLost = TRUE;
m_dwSessionLostReason = DISCONNNECT_REASON_UNKNOWN;
for( DWORD dwIndex = 0; dwIndex < MAX_SESSIONS; dwIndex++ )
{
m_pHostAddresses[dwIndex] = NULL;
m_pDeviceAddresses[dwIndex] = NULL;
}
InitializeCriticalSection( &m_csLock );
InitializeCriticalSection( &m_csThreadCountLock );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
CDPlay8Client::~CDPlay8Client()
{
DeleteCriticalSection( &m_csLock );
DeleteCriticalSection( &m_csThreadCountLock );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CDPlay8Client::Init(MazeConfig* pMazeConfig)
{
HRESULT hr;
m_MazeConfig = pMazeConfig;
Shutdown();
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Client, NULL,
CLSCTX_ALL, IID_IDirectPlay8Client,
(LPVOID*) &m_pDPlay ) ) )
return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
if( FAILED( hr = m_pDPlay->Initialize( this, StaticReceiveHandler, 0 ) ) )
return DXTRACE_ERR( TEXT("Initialize"), hr );
// If between Range, attempt to set SPThreads.
if((m_MazeConfig->dwSPThreads >= MIN_SP_THREADS) && (m_MazeConfig->dwSPThreads <= MAX_SP_THREADS))
{
SetNumSPThreads(m_MazeConfig->dwSPThreads);
}
// If less than MAX, set our SP Buffer.
if(m_MazeConfig->dwSPBufferSize <= MAX_SP_BUFFER)
{
SetSPBuffer(m_MazeConfig->dwSPBufferSize);
}
m_fLastUpdateConnectInfoTime = DXUtil_Timer( TIMER_GETAPPTIME );
m_bSessionLost = TRUE;
m_dwNumSessions = 0;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
DWORD CDPlay8Client::GetNumSPThreads()
{
HRESULT hr = DPN_OK;
DPN_SP_CAPS dnSPCaps;
DWORD dwFlags = NULL;
DWORD dwNumSPThreads = NULL;
DXTRACE_MSG( TEXT("Attempting to Get SP Thread Count.") );
dnSPCaps.dwSize = sizeof(DPN_SP_CAPS);
hr = m_pDPlay->GetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
if(hr != DPN_OK)
{
DXTRACE_ERR( TEXT("GetSPCaps error"), hr );
dwNumSPThreads = 0;
}
else
{
dwNumSPThreads = dnSPCaps.dwNumThreads;
}
return dwNumSPThreads;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CDPlay8Client::SetNumSPThreads(DWORD dwNumSPThreads)
{
HRESULT hr = DPN_OK;
DPN_SP_CAPS dnSPCaps;
DWORD dwFlags = NULL;
dnSPCaps.dwSize = sizeof(DPN_SP_CAPS);
hr = m_pDPlay->GetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
if(hr == DPN_OK)
{
if((dwNumSPThreads >= MIN_SP_THREADS) && (dwNumSPThreads <= MAX_SP_THREADS))
{
dnSPCaps.dwNumThreads = dwNumSPThreads;
// Attempt to set the number of SP Threads.
hr = m_pDPlay->SetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
if(hr != DPN_OK)
{
DXTRACE_ERR( TEXT("SetSPCaps error."), hr );
}
}
}
else
{
DXTRACE_ERR( TEXT("GetSPCaps error."), hr );
}
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
DWORD CDPlay8Client::GetSPBuffer()
{
HRESULT hr = DPN_OK;
DPN_SP_CAPS dnSPCaps;
DWORD dwFlags = NULL;
DWORD dwSPBufferSize = NULL;
DXTRACE_MSG( TEXT("Attempting to Get SP Buffer Size.") );
dnSPCaps.dwSize = sizeof(DPN_SP_CAPS);
hr = m_pDPlay->GetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
if(hr != DPN_OK)
{
DXTRACE_ERR( TEXT("GetSPCaps error"), hr );
dwSPBufferSize = 0xffffffff;
}
else
{
dwSPBufferSize = dnSPCaps.dwSystemBufferSize;
}
return dwSPBufferSize;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CDPlay8Client::SetSPBuffer(DWORD dwSPBufferSize)
{
HRESULT hr = DPN_OK;
DPN_SP_CAPS dnSPCaps;
DWORD dwFlags = NULL;
dnSPCaps.dwSize = sizeof(DPN_SP_CAPS);
hr = m_pDPlay->GetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
if(hr == DPN_OK)
{
if(dwSPBufferSize <= MAX_SP_BUFFER)
dnSPCaps.dwSystemBufferSize = dwSPBufferSize;
// Attempt to set the number of SP Threads.
hr = m_pDPlay->SetSPCaps(&CLSID_DP8SP_TCPIP, &dnSPCaps, dwFlags);
if(hr != DPN_OK)
{
DXTRACE_ERR( TEXT("SetSPCaps error."), hr );
}
}
else // !GetSPCase != DPN_OK
{
DXTRACE_ERR( TEXT("GetSPCaps error."), hr );
}
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CDPlay8Client::Shutdown()
{
for( DWORD dwIndex = 0; dwIndex < MAX_SESSIONS; dwIndex++ )
{
SAFE_RELEASE( m_pHostAddresses[dwIndex] );
SAFE_RELEASE( m_pDeviceAddresses[dwIndex] );
}
if( m_dpnhEnum != NULL )
{
// Cancel the enumeration if its in progress, and ignore any errors
m_pDPlay->CancelAsyncOperation( m_dpnhEnum, 0 );
m_dpnhEnum = NULL;
}
if( m_pDPlay != NULL )
m_pDPlay->Close(0);
SAFE_RELEASE( m_pDPlay );
m_bSessionLost = TRUE;
m_dwNumSessions = 0;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CDPlay8Client::StartSessionEnum( const TCHAR* ipaddress )
{
if( NULL == m_pDPlay )
return E_FAIL;
DPN_APPLICATION_DESC dpnAppDesc;
IDirectPlay8Address* pDP8AddressHost = NULL;
IDirectPlay8Address* pDP8AddressLocal = NULL;
WCHAR* wszHostName = NULL;
HRESULT hr;
DWORD dwPort;
m_dwNumSessions = 0;
if( m_dpnhEnum != NULL )
{
// If an enumeration is already running, cancel
// it and start a new one. Ignore any errors from CancelAsyncOperation
m_pDPlay->CancelAsyncOperation( m_dpnhEnum, 0 );
m_dpnhEnum = NULL;
}
// Create the local device address object
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
CLSCTX_ALL, IID_IDirectPlay8Address,
(LPVOID*) &pDP8AddressLocal ) ) )
{
DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
goto LCleanup;
}
// Set IP service provider
if( FAILED( hr = pDP8AddressLocal->SetSP( &CLSID_DP8SP_TCPIP ) ) )
{
DXTRACE_ERR( TEXT("SetSP"), hr );
goto LCleanup;
}
// Create the remote host address object
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
CLSCTX_ALL, IID_IDirectPlay8Address,
(LPVOID*) &pDP8AddressHost ) ) )
{
DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
goto LCleanup;
}
// Set IP service provider
if( FAILED( hr = pDP8AddressHost->SetSP( &CLSID_DP8SP_TCPIP ) ) )
{
DXTRACE_ERR( TEXT("SetSP"), hr );
goto LCleanup;
}
// Maze uses a fixed port, so add it to the host address
dwPort = DPMAZESERVER_PORT;
hr = pDP8AddressHost->AddComponent( DPNA_KEY_PORT,
&dwPort, sizeof(dwPort),
DPNA_DATATYPE_DWORD );
if( FAILED(hr) )
{
DXTRACE_ERR( TEXT("AddComponent"), hr );
goto LCleanup;
}
// Set the remote host name (if provided)
if( ipaddress != NULL && ipaddress[0] != 0 )
{
wszHostName = new WCHAR[_tcslen(ipaddress)+1];
DXUtil_ConvertGenericStringToWide( wszHostName, ipaddress );
hr = pDP8AddressHost->AddComponent( DPNA_KEY_HOSTNAME, wszHostName,
(wcslen(wszHostName)+1)*sizeof(WCHAR),
DPNA_DATATYPE_STRING );
if( FAILED(hr) )
{
DXTRACE_ERR( TEXT("AddComponent"), hr );
goto LCleanup;
}
}
ZeroMemory( &dpnAppDesc, sizeof( DPN_APPLICATION_DESC ) );
dpnAppDesc.dwSize = sizeof( DPN_APPLICATION_DESC );
dpnAppDesc.guidApplication = StressMazeAppGUID;
// Enumerate all StressMazeApp hosts running on IP service providers
hr = m_pDPlay->EnumHosts( &dpnAppDesc, pDP8AddressHost,
pDP8AddressLocal, NULL,
0, INFINITE, 0, INFINITE, NULL,
&m_dpnhEnum, 0 );
if( hr != DPNERR_PENDING && FAILED(hr) )
{
DXTRACE_ERR_NOMSGBOX( TEXT("EnumHosts"), hr );
goto LCleanup;
}
LCleanup:
SAFE_RELEASE( pDP8AddressHost);
SAFE_RELEASE( pDP8AddressLocal );
SAFE_DELETE( wszHostName );
return hr;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CDPlay8Client::StopSessionEnum()
{
if( NULL == m_pDPlay )
return E_FAIL;
// If an enumeration is already running, cancel it and ignore
// any errors from CancelAsyncOperation
if( m_dpnhEnum != NULL )
{
m_pDPlay->CancelAsyncOperation( m_dpnhEnum, 0 );
m_dpnhEnum = NULL;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
BOOL CDPlay8Client::EnumSessionCallback( const DPN_APPLICATION_DESC *pdesc,
IDirectPlay8Address* pDP8AddressHost,
IDirectPlay8Address* pDP8AddressDevice )
{
if( NULL == m_pDPlay )
return DPN_OK;
EnterCriticalSection( &m_csLock );
if( m_dwNumSessions < MAX_SESSIONS )
{
// Search for existing record for this session, if
// there is one, break this loop so we just update
// the current entry.
for( DWORD dwIndex = 0; dwIndex < m_dwNumSessions; dwIndex++ )
{
if( m_Sessions[dwIndex].guidInstance == pdesc->guidInstance )
break;
}
memcpy( &m_Sessions[dwIndex], pdesc, sizeof( DPN_APPLICATION_DESC ) );
// Copy pDP8AddressHost to m_pHostAddresses[dwIndex]
SAFE_RELEASE( m_pHostAddresses[dwIndex] );
pDP8AddressHost->QueryInterface( IID_IDirectPlay8Address,
(LPVOID*) &m_pHostAddresses[dwIndex] );
// Copy pDP8AddressDevice to m_pDeviceAddresses[dwIndex]
SAFE_RELEASE( m_pDeviceAddresses[dwIndex] );
pDP8AddressDevice->QueryInterface( IID_IDirectPlay8Address,
(LPVOID*) &m_pDeviceAddresses[dwIndex] );
if( pdesc->pwszSessionName != NULL )
{
DXUtil_ConvertWideStringToGeneric( m_szSessionNames[dwIndex],
pdesc->pwszSessionName );
}
else
{
_tcscpy( m_szSessionNames[dwIndex], TEXT("Untitled") );
}
if( m_dwNumSessions == dwIndex )
m_dwNumSessions++;
}
LeaveCriticalSection( &m_csLock );
return DPN_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CDPlay8Client::JoinSession( DWORD num )
{
HRESULT hr;
IDirectPlay8Address* pHostAddress = NULL;
IDirectPlay8Address* pDeviceAddress = NULL;
if( m_pDPlay == NULL )
return E_FAIL;
DXTRACE( TEXT("MazeClient: Trying to connect to server\n") );
DPN_APPLICATION_DESC dpnAppDesc;
ZeroMemory( &dpnAppDesc, sizeof( DPN_APPLICATION_DESC ) );
dpnAppDesc.dwSize = sizeof( DPN_APPLICATION_DESC );
dpnAppDesc.guidApplication = StressMazeAppGUID;
dpnAppDesc.guidInstance = m_Sessions[num].guidInstance;
EnterCriticalSection( &m_csLock );
// Copy the host and device address pointers, and addref them.
// If this is not done, then there is a rare chance that
// EnumSessionCallback() may be called during the Connect() call
// and destory the address before DirectPlay gets a chance to copy them.
pHostAddress = m_pHostAddresses[num];
pHostAddress->AddRef();
pDeviceAddress = m_pDeviceAddresses[num];
pDeviceAddress->AddRef();
LeaveCriticalSection( &m_csLock );
// Connect to the remote host
// The enumeration is automatically canceled after Connect is called
if( FAILED( hr = m_pDPlay->Connect( &dpnAppDesc, // Application description
pHostAddress, // Session host address
pDeviceAddress, // Address of device used to connect to the host
NULL, NULL, // Security descriptions & credientials (MBZ in DPlay8)
NULL, 0, // User data & its size
NULL, // Asynchronous connection context (returned with DPNMSG_CONNECT_COMPLETE in async handshaking)
NULL, // Asynchronous connection handle (used to cancel connection process)
DPNOP_SYNC ) ) ) // Connect synchronously
{
if( hr == DPNERR_NORESPONSE || hr == DPNERR_ABORTED )
goto LCleanup; // These are possible if the server exits while joining
if( hr == DPNERR_INVALIDINSTANCE )
goto LCleanup; // This is possible if the original server exits and another server comes online while we are connecting
DXTRACE_ERR_NOMSGBOX( TEXT("Connect"), hr );
goto LCleanup;
}
m_bSessionLost = FALSE;
DXTRACE( TEXT("MazeClient: Connected to server. Enum automatically canceled\n") );
UpdateConnectionInfo();
m_fLastUpdateConnectInfoTime = DXUtil_Timer( TIMER_GETAPPTIME );
LCleanup:
SAFE_RELEASE( pHostAddress );
SAFE_RELEASE( pDeviceAddress );
return hr;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CDPlay8Client::SendPacket( void* pData, DWORD dwSize,
BOOL bGuaranteed, DWORD dwTimeout )
{
if( NULL == m_pDPlay )
return S_OK;
DPNHANDLE hAsync;
DWORD dwFlags;
DPNHANDLE* phAsync;
if( bGuaranteed )
{
// If we are guaranteed then we must specify
// DPNSEND_NOCOMPLETE and pass in non-null for the
// pvAsyncContext
dwFlags = DPNSEND_GUARANTEED;
}
else
{
// If we aren't guaranteed then we can
// specify DPNSEND_NOCOMPLETE. And when
// DPNSEND_NOCOMPLETE is on pvAsyncContext
// must be NULL.
dwFlags = DPNSEND_NOCOMPLETE;
}
// Must pass in a value for the Asyn handle. Will be thrown when proc completes.
phAsync = &hAsync;
DPN_BUFFER_DESC dpnBufferDesc;
dpnBufferDesc.dwBufferSize = dwSize;
dpnBufferDesc.pBufferData = (PBYTE) pData;
// Update the throughput counter
m_dwThroughputBytes += dwSize;
// DirectPlay will tell via the message handler
// if there are any severe errors, so ignore any errors
m_pDPlay->Send( &dpnBufferDesc, 1, dwTimeout,
NULL, phAsync, dwFlags );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CDPlay8Client::StaticReceiveHandler( void *pvContext, DWORD dwMessageType,
void *pvMessage )
{
CDPlay8Client* pThisObject = (CDPlay8Client*) pvContext;
return pThisObject->ReceiveHandler( pvContext, dwMessageType, pvMessage );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CDPlay8Client::ReceiveHandler( void *pvContext, DWORD dwMessageType,
void *pvMessage )
{
// Increment our Active Thread Counter.
EnterCriticalSection( &m_csThreadCountLock );
//Get the time when we entered the Message Handler
FLOAT fStartTime = DXUtil_Timer( TIMER_GETAPPTIME );
m_wActiveThreadCount++;
if(m_wActiveThreadCount > m_wMaxThreadCount)
m_wMaxThreadCount = m_wActiveThreadCount;
// Calculate an average.
FLOAT fdiff = m_wActiveThreadCount - m_fAvgThreadCount;
m_fAvgThreadCount += fdiff/8;
LeaveCriticalSection( &m_csThreadCountLock );
switch( dwMessageType )
{
case DPN_MSGID_RECEIVE:
{
PDPNMSG_RECEIVE pRecvData = (PDPNMSG_RECEIVE) pvMessage;
// Update the throughput counter
m_dwThroughputBytes += pRecvData->dwReceiveDataSize;
if( m_pClient != NULL )
{
m_pClient->OnPacket( pRecvData->dpnidSender,
pRecvData->pReceiveData,
pRecvData->dwReceiveDataSize );
}
break;
}
case DPN_MSGID_TERMINATE_SESSION:
{
m_dwSessionLostReason = DISCONNNECT_REASON_UNKNOWN;
PDPNMSG_TERMINATE_SESSION pTermMsg = (PDPNMSG_TERMINATE_SESSION) pvMessage;
// The MazeServer passes a DWORD in pvTerminateData if
// it disconnected us, otherwise it will be null.
if( pTermMsg->pvTerminateData != NULL )
{
DWORD* pdw = (DWORD*) pTermMsg->pvTerminateData;
m_dwSessionLostReason = *pdw;
}
if( m_pClient != NULL )
m_pClient->OnSessionLost( m_dwSessionLostReason );
// Now that the session is lost we need to restart DirectPlay by calling
// Close() and Init() on m_pDPlay, however this can not be
// done in the DirectPlay message callback, so the main thread will
// do this when IsSessionLost() returns TRUE
m_bSessionLost = TRUE;
break;
}
case DPN_MSGID_ENUM_HOSTS_RESPONSE:
{
PDPNMSG_ENUM_HOSTS_RESPONSE pEnumResponse = (PDPNMSG_ENUM_HOSTS_RESPONSE) pvMessage;
EnumSessionCallback( pEnumResponse->pApplicationDescription,
pEnumResponse->pAddressSender,
pEnumResponse->pAddressDevice );
break;
}
}
EnterCriticalSection( &m_csThreadCountLock );
m_wActiveThreadCount-- ;
// Calculate an average.
FLOAT fDiffTime = ( DXUtil_Timer( TIMER_GETAPPTIME ) - fStartTime ) - m_fAvgThreadTime;
m_fAvgThreadTime += fDiffTime/8;
//Get the Max time in the thread.
if ( fDiffTime > m_fMaxThreadTime )
{
m_fMaxThreadTime = fDiffTime;
}
LeaveCriticalSection( &m_csThreadCountLock );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CDPlay8Client::UpdateConnectionInfo()
{
if( NULL == m_pDPlay )
return E_FAIL;
// Update the DPN_CONNECTION_INFO every 1/2 second...
float fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
if( fCurTime - m_fLastUpdateConnectInfoTime > 0.5f )
{
// Call GetConnectionInfo to get DirectPlay stats about connection
ZeroMemory( &m_dpnConnectionInfo, sizeof(DPN_CONNECTION_INFO) );
m_dpnConnectionInfo.dwSize = sizeof(DPN_CONNECTION_INFO);
m_pDPlay->GetConnectionInfo( &m_dpnConnectionInfo, 0 );
// Call GetSendQueueInfo to get DirectPlay stats about messages
m_pDPlay->GetSendQueueInfo( &m_dwHighPriMessages, &m_dwHighPriBytes,
DPNGETSENDQUEUEINFO_PRIORITY_HIGH );
m_pDPlay->GetSendQueueInfo( &m_dwNormalPriMessages, &m_dwNormalPriBytes,
DPNGETSENDQUEUEINFO_PRIORITY_NORMAL );
m_pDPlay->GetSendQueueInfo( &m_dwLowPriMessages, &m_dwLowPriBytes,
DPNGETSENDQUEUEINFO_PRIORITY_LOW );
m_fLastUpdateConnectInfoTime = fCurTime;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
DWORD CDPlay8Client::GetThroughputBPS()
{
static float s_fLastThroughputBPSTime = DXUtil_Timer( TIMER_GETAPPTIME );
float fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
if( fCurTime - s_fLastThroughputBPSTime > 1.0f )
{
m_fThroughputBPS = (float) m_dwThroughputBytes / (fCurTime - s_fLastThroughputBPSTime);
s_fLastThroughputBPSTime = fCurTime;
m_dwThroughputBytes = 0;
}
return (DWORD) m_fThroughputBPS;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
DWORD CDPlay8Client::GetRoundTripLatencyMS()
{
UpdateConnectionInfo();
return m_dpnConnectionInfo.dwRoundTripLatencyMS;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CDPlay8Client::GetConnectionInfo( TCHAR* strConnectionInfo )
{
UpdateConnectionInfo();
_stprintf( strConnectionInfo,
TEXT(" Thread Count: Current=%d Avg= %.2f Max=%d\n") \
TEXT(" Thread Time: Avg= %.4f Max=%.4f(s)\n") \
\
TEXT(" Round Trip Latency MS=%dms\n") \
TEXT(" Throughput BPS: Current=%d Peak=%d\n") \
\
TEXT(" Messages Received=%d\n") \
\
TEXT(" Sent: GB=%d GP=%d NGB=%d NGP=%d\n") \
TEXT(" Received: GB=%d GP=%d NGB=%d NGP=%d\n") \
\
TEXT(" Messages Transmitted: HP=%d NP=%d LP=%d\n") \
TEXT(" Messages Timed Out: HP=%d NP=%d LP=%d\n") \
\
TEXT(" Retried: GB=%d GP=%d\n") \
TEXT(" Dropped: NGB=%d NGP=%d\n") \
\
TEXT(" Send Queue Messages: HP=%d NP=%d LP=%d\n") \
TEXT(" Send Queue Bytes: HP=%d NP=%d LP=%d\n"), \
\
\
\
m_wActiveThreadCount, m_fAvgThreadCount, m_wMaxThreadCount,
m_fAvgThreadTime, m_fMaxThreadTime,
m_dpnConnectionInfo.dwRoundTripLatencyMS,
m_dpnConnectionInfo.dwThroughputBPS,
m_dpnConnectionInfo.dwPeakThroughputBPS,
m_dpnConnectionInfo.dwMessagesReceived,
m_dpnConnectionInfo.dwBytesSentGuaranteed,
m_dpnConnectionInfo.dwPacketsSentGuaranteed,
m_dpnConnectionInfo.dwBytesSentNonGuaranteed,
m_dpnConnectionInfo.dwPacketsSentNonGuaranteed,
m_dpnConnectionInfo.dwBytesReceivedGuaranteed,
m_dpnConnectionInfo.dwPacketsReceivedGuaranteed,
m_dpnConnectionInfo.dwBytesReceivedNonGuaranteed,
m_dpnConnectionInfo.dwPacketsReceivedNonGuaranteed,
m_dpnConnectionInfo.dwMessagesTransmittedHighPriority,
m_dpnConnectionInfo.dwMessagesTransmittedNormalPriority,
m_dpnConnectionInfo.dwMessagesTransmittedLowPriority,
m_dpnConnectionInfo.dwMessagesTimedOutHighPriority,
m_dpnConnectionInfo.dwMessagesTimedOutNormalPriority,
m_dpnConnectionInfo.dwMessagesTimedOutLowPriority,
m_dpnConnectionInfo.dwBytesRetried,
m_dpnConnectionInfo.dwPacketsRetried,
m_dpnConnectionInfo.dwBytesDropped,
m_dpnConnectionInfo.dwPacketsDropped,
m_dwHighPriMessages, m_dwNormalPriMessages, m_dwLowPriMessages,
m_dwHighPriBytes, m_dwNormalPriBytes, m_dwLowPriBytes
);
return S_OK;
}