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,901 @@
//----------------------------------------------------------------------------
// File: mazeapp.cpp
//
// Desc: see main.cpp
//
// Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
//-----------------------------------------------------------------------------
#define STRICT
#define D3D_OVERLOADS
#include <windows.h>
#include <d3dx.h>
#include <stdio.h>
#include <tchar.h>
#include <math.h>
#include <process.h>
#include <dxerr8.h>
#include <dplay8.h>
#include "DXUtil.h"
#include "SyncObjects.h"
#include "DummyConnector.h"
#include "DPlay8Client.h"
#include "MazeClient.h"
#include "IMazeGraphics.h"
#include "MazeApp.h"
static CMazeApp* s_pMazeApp = NULL;
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
CMazeApp::CMazeApp()
{
s_pMazeApp = this;
m_hOutputMsgThread = NULL;
m_bQuitThread = NULL;
m_hOutputMsgEvent = NULL;
m_dwNextOutputMsg = 0;
m_bLocalLoopback = TRUE;
m_bAllowConnect = FALSE;
m_bConnectNow = TRUE;
m_bSaveSettings = TRUE;
m_lQueueSize = 0;
m_dwNextFreeOutputMsg = 0;
m_hLogFile = NULL;
m_bLocalLoopbackInitDone = FALSE;
m_bInitDone = FALSE;
// Create an event object to flag pending output messages
m_hOutputMsgEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
//Initialize our Config structure to 0.
ZeroMemory(&m_Config, sizeof(m_Config));
//Must init buffer size to -1, since 0 is valid.
m_Config.dwSPBufferSize = 0xffffffff;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
CMazeApp::~CMazeApp()
{
CloseHandle( m_hOutputMsgEvent );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CMazeApp::Create( IMazeGraphics* pMazeGraphics )
{
m_pMazeGraphics = pMazeGraphics;
if( m_pMazeGraphics == NULL )
return E_FAIL;
m_pMazeGraphics->Init( this, &m_DP8Client, &m_MazeClient );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
int CMazeApp::Run( HINSTANCE hInst )
{
if( NULL == m_pMazeGraphics )
return 0;
// Start the timer and init the random seed
DXUtil_Timer( TIMER_START );
DWORD dwSRand = (DWORD) (DXUtil_Timer( TIMER_GETABSOLUTETIME ) * UINT_MAX * (DWORD)GetCurrentThreadId() );
srand( dwSRand );
// Tell OS's that have power management to not
// sleep, since this app will be using the
// network connection and need very little user input
SuspendPowerManagement();
// Initialize COM
CoInitializeEx( NULL, COINIT_MULTITHREADED );
// Extract configuration settings from the registry
ReadConfig();
if( m_Config.bFileLogging )
CreateTempLogFile();
if( SUCCEEDED( m_pMazeGraphics->Create( hInst ) ) )
{
ConsolePrintf( LINE_LOG, TEXT("DirectPlayMaze client started.") );
// Spin up a thread to record/display the output
UINT dwOutputMsgThreadID;
m_hOutputMsgThread = (HANDLE)_beginthreadex( NULL, 0, StaticOutputMsgThread,
NULL, 0, &dwOutputMsgThreadID );
// Initialize maze client object - basically just build the maze
m_MazeClient.Init( this, m_pMazeGraphics );
m_pMazeGraphics->Run();
// Wait for threads to shutdown
DXUtil_Trace( TEXT("Quiting\n") );
m_bQuitThread = TRUE;
SetEvent( m_hOutputMsgEvent );
WaitForSingleObject( m_hOutputMsgThread, INFINITE );
CloseHandle( m_hOutputMsgThread );
// Write configuration settings to registry
WriteConfig();
m_pMazeGraphics->Shutdown();
}
// Clean up
DXUtil_Trace( TEXT("Shutting down client\n") );
m_MazeClient.Shutdown();
DXUtil_Trace( TEXT("Shutting down dp8\n") );
m_DP8Client.Shutdown();
CoUninitialize();
return 0;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CMazeApp::SuspendPowerManagement()
{
TCHAR szPath[MAX_PATH];
HINSTANCE hInstKernel32 = NULL;
typedef EXECUTION_STATE (WINAPI* LPSETTHREADEXECUTIONSTATE)( EXECUTION_STATE esFlags );
LPSETTHREADEXECUTIONSTATE pSetThreadExecutionState = NULL;
GetSystemDirectory(szPath, MAX_PATH);
// SetThreadExecutionState() isn't availible on some old OS's,
// so do a LoadLibrary to get to it.
lstrcat(szPath, TEXT("\\kernel32.dll"));
hInstKernel32 = LoadLibrary(szPath);
if (hInstKernel32 != NULL)
{
pSetThreadExecutionState = (LPSETTHREADEXECUTIONSTATE)GetProcAddress(hInstKernel32, "SetThreadExecutionState");
if( pSetThreadExecutionState != NULL )
{
// Tell OS's that have power management to not
// sleep, since this app will be using the
// network connection and need very little user input
pSetThreadExecutionState( ES_SYSTEM_REQUIRED | ES_CONTINUOUS );
}
FreeLibrary(hInstKernel32);
}
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CMazeApp::FrameMove( FLOAT fElapsedTime )
{
HRESULT hr;
FLOAT fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
static FLOAT s_fLastConnect = INT_MIN;
static FLOAT s_fStartEnumTime = INT_MIN;
static FLOAT s_fStopEnumTime = INT_MIN;
static FLOAT s_fEnumStarted = FALSE;
if( m_DP8Client.IsSessionLost() )
{
if( FALSE == m_bLocalLoopbackInitDone )
{
if( m_bInitDone )
{
ConsolePrintf( LINE_LOG, TEXT("Disconnected from server") );
if( m_DP8Client.GetSessionLostReason() == DISCONNNECT_REASON_CLIENT_OUT_OF_DATE )
{
ConsolePrintf( LINE_LOG, TEXT("Disconnected because MazeClient is out of date.") );
ConsolePrintf( LINE_LOG, TEXT("Please get updated version") );
ConsolePrintf( LINE_LOG, TEXT("from http://msdn.microsoft.com/directx/") );
m_bOutOfDateClient = TRUE;
}
// Disconnected, so retry in 10 seconds
s_fStopEnumTime = fCurTime - m_Config.dwNetworkRetryDelay * 60.0f + 10.0f;
}
else
{
// If just starting up, then retry immediately
m_bInitDone = TRUE;
}
m_MazeClient.LockWorld();
m_MazeClient.Reset();
// Now that the session is lost we need to
// restart DirectPlay by calling Close()
// and Init() on m_pDPlay
m_DP8Client.Shutdown();
//Pass in the our structure in order to get out configuration data.
m_DP8Client.Init(GetConfig());
if( m_bAllowLoopback )
InitServerForLoopback();
m_MazeClient.UnlockWorld();
m_bLocalLoopbackInitDone = TRUE;
}
if( ( !s_fEnumStarted && fCurTime - s_fStopEnumTime > m_Config.dwNetworkRetryDelay * 60.0f || m_bConnectNow )
&& m_bAllowConnect && !m_bOutOfDateClient )
{
m_bConnectNow = FALSE;
if( SUCCEEDED( hr = StartSessionEnum() ) )
{
// DirectPlay host enumeration started
ConsolePrintf( LINE_LOG, TEXT("Starting DirectPlay host enumeration") );
s_fStartEnumTime = fCurTime;
s_fEnumStarted = TRUE;
}
else
{
//If we are in the stress connect, try the next connection.
//When we get back to 1, then we have gone through the list, so let's wait.
if(m_Config.dwStressConnect > 1)
{
//We are going through the list of machines to attempt connection. So lets try the next right away.
ConsolePrintf( LINE_LOG, TEXT("Host not found. Trying local subnet.") );
m_bConnectNow = TRUE; //Try the enum right away with the next item in the list.
}
else
{
ConsolePrintf( LINE_LOG, TEXT("DirectPlay host enumeration failed to start.") );
ConsolePrintf( LINE_LOG, TEXT("Will try again in %d minutes."), m_Config.dwNetworkRetryDelay );
}
// DirectPlay host enumeration failed to start
// Will try again in m_Config.dwNetworkRetryDelay minutes
s_fStopEnumTime = fCurTime;
s_fEnumStarted = FALSE;
}
}
if( s_fEnumStarted && fCurTime - s_fStartEnumTime > 5.0f * 60.0f )
{
//If we are in the stress connect, try the next connection.
//When we get back to 1, then we have gone through the list, so let's start over.
if(m_Config.dwStressConnect > 1)
{
//We are going through the list of machines to attempt connection. So lets try the next right away.
ConsolePrintf( LINE_LOG, TEXT("Host not found. Trying local subnet.") );
m_bConnectNow = TRUE; //Try the enum right away with the next item in the list.
}
else
{
ConsolePrintf( LINE_LOG, TEXT("No host found. Stopping DirectPlay host enumeration") );
ConsolePrintf( LINE_LOG, TEXT("Will try again in %d minutes."), m_Config.dwNetworkRetryDelay );
}
// Stop enumeration
m_DP8Client.StopSessionEnum();
s_fStopEnumTime = fCurTime;
s_fEnumStarted = FALSE;
}
if( s_fEnumStarted && fCurTime - s_fLastConnect > 0.5f )
{
if( TRUE == TryToConnect() )
{
// Connect successful
ConsolePrintf( LINE_LOG, TEXT("Connected to server. Host enumeration stopped.") );
m_bLocalLoopback = FALSE;
s_fEnumStarted = FALSE;
m_bLocalLoopbackInitDone = FALSE;
}
s_fLastConnect = fCurTime;
}
m_bDisconnectNow = FALSE;
}
else
{
m_bLocalLoopbackInitDone = FALSE;
if( m_Config.dwLogLevel > 1 )
{
// Display position every so often
static float fLastPosUpdate = fCurTime;
if( fCurTime - fLastPosUpdate > 10.0f )
{
D3DXVECTOR3 vPos = m_MazeClient.GetCameraPos();
DWORD dwNumPlayers, dwNumNearbyPlayers;
m_MazeClient.GetPlayerStats( &dwNumPlayers, &dwNumNearbyPlayers );
ConsolePrintf( LINE_LOG, TEXT("Position: (%5.1f,%5.1f), Players: %d, Nearby Players: %d"),
vPos.x, vPos.z, dwNumPlayers, dwNumNearbyPlayers );
fLastPosUpdate = fCurTime;
}
}
// Display connection info every so often
static float fLastLogUpdate = fCurTime;
if( m_Config.dwAutoPrintStats > 0 &&
fCurTime - fLastLogUpdate > m_Config.dwAutoPrintStats * 60.0f )
{
D3DXVECTOR3 vPos = m_MazeClient.GetCameraPos();
DWORD dwNumPlayers, dwNumNearbyPlayers;
m_MazeClient.GetPlayerStats( &dwNumPlayers, &dwNumNearbyPlayers );
ConsolePrintf( LINE_LOG, TEXT("Position: (%5.1f,%5.1f), Players: %d, Nearby Players: %d"),
vPos.x, vPos.z, dwNumPlayers, dwNumNearbyPlayers );
TCHAR strInfo[5000];
TCHAR* strEndOfLine;
TCHAR* strStartOfLine;
// Query the IOutboudNet for info about the connection to this user
m_DP8Client.GetConnectionInfo( strInfo );
ConsolePrintf( LINE_LOG, TEXT("Displaying connection info for 0x%0.8x"), m_MazeClient.GetLocalClientID() );
ConsolePrintf( LINE_LOG, TEXT("(Key: G=Guaranteed NG=Non-Guaranteed B=Bytes P=Packets)") );
// Display each line seperately
strStartOfLine = strInfo;
while( TRUE )
{
strEndOfLine = _tcschr( strStartOfLine, '\n' );
if( strEndOfLine == NULL )
break;
*strEndOfLine = 0;
ConsolePrintf( LINE_LOG, strStartOfLine );
strStartOfLine = strEndOfLine + 1;
}
fLastLogUpdate = fCurTime;
}
// If we are testing connect/disconnect, break after so many iterations.
if( m_Config.bAutoDisconnnect )
{
// Disconnect between 5-25seconds
static float fDisconnectCountdown = 10.0f;
fDisconnectCountdown -= fElapsedTime;
if( fDisconnectCountdown < 0.0f )
{
fDisconnectCountdown = (float)(rand() % 20000 + 5000 ) / 1000.0f;
ConsolePrintf( LINE_LOG, TEXT("Intentional disconnect. Connecting again for %0.0f seconds..."), fDisconnectCountdown );
m_DP8Client.Shutdown();
m_MazeClient.Shutdown();
}
}
if( m_bDisconnectNow )
{
m_bDisconnectNow = FALSE;
ConsolePrintf( LINE_LOG, TEXT("Intentional disconnect.") );
m_DP8Client.Shutdown();
m_MazeClient.Shutdown();
if( m_bAllowLoopback )
InitServerForLoopback();
}
}
// Update state of client
m_MazeClient.Update( fElapsedTime );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CMazeApp::StartSessionEnum()
{
HRESULT hr;
// If we're not the preview, then enum sessions
if( m_pMazeGraphics->IsPreview() )
return S_OK;
// Start enumerating available sessions at specified IP address.
if( m_Config.bConnectToMicrosoftSite )
{
ConsolePrintf( LINE_LOG, TEXT("Connecting to DirectPlayMaze.rte.microsoft.com") );
hr = m_DP8Client.StartSessionEnum( MICROSOFT_SERVER );
}
else if( m_Config.bConnectToLocalServer )
{
ConsolePrintf( LINE_LOG, TEXT("Connecting to local server (searches the local subnet)") );
hr = m_DP8Client.StartSessionEnum( TEXT("") );
}
else if( m_Config.bConnectToRemoteServer )
{
ConsolePrintf( LINE_LOG, TEXT("Connecting to remote server at '%s'"), m_Config.szIPAddress );
hr = m_DP8Client.StartSessionEnum( m_Config.szIPAddress );
}
// If users wants Stress Connect, go through the sequence they have requested.
else if( m_Config.dwStressConnect )
{
if( m_Config.dwStressConnect == 1 )
{
// Point to local subnet for next enum.
m_Config.dwStressConnect = 2;
ConsolePrintf( LINE_LOG, TEXT("Connecting to remote server at '%s'"), m_Config.szIPAddress );
hr = m_DP8Client.StartSessionEnum( m_Config.szIPAddress );
}
else
{
// Point back at remote server for next enum.
m_Config.dwStressConnect = 1;
// Must equal 2 or something higher. Try the local subnet.
ConsolePrintf( LINE_LOG, TEXT("Connecting to local server (searches the local subnet)") );
hr = m_DP8Client.StartSessionEnum( TEXT("") );
}
}
return hr;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
BOOL CMazeApp::TryToConnect()
{
if( m_DP8Client.GetNumSessions() > 0 )
{
m_MazeClient.Reset();
m_MazeClient.SetOutboundClient( m_DP8Client.GetOutboundClient() );
m_DP8Client.SetClient( &m_MazeClient );
// Loop through the available sessions and attempt to connect
for( DWORD i = 0; i < m_DP8Client.GetNumSessions(); i++ )
{
if( SUCCEEDED(m_DP8Client.JoinSession( i ) ) )
{
return TRUE;
}
}
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
HRESULT CMazeApp::InitServerForLoopback()
{
HRESULT hr;
m_bLocalLoopback = TRUE;
#define LOOPBACK_MAZE_WIDTH 16
#define LOOPBACK_MAZE_HEIGHT 16
// Initalize maze and server objects for loopback mode
if( FAILED( hr = m_MazeClient.m_Maze.Init( LOOPBACK_MAZE_WIDTH,
LOOPBACK_MAZE_HEIGHT,
DEFAULT_SEED ) ) )
{
return DXTRACE_ERR( TEXT("m_Maze.Init"), hr );
}
// Initialize maze server object - hook up to the maze object in the client
m_MazeServer.Init( m_bLocalLoopback, &m_MazeClient.m_Maze );
m_DummyClientConnection.SetTarget( &m_MazeServer );
m_MazeClient.SetOutboundClient( &m_DummyClientConnection );
m_DummyServerConnection.SetTarget( &m_MazeClient );
m_MazeServer.SetOutboundServer( &m_DummyServerConnection );
m_DummyClientConnection.Connect( 2 );
m_MazeClient.EngageAutopilot( TRUE );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
UINT WINAPI CMazeApp::StaticOutputMsgThread( LPVOID pParam )
{
return s_pMazeApp->OutputMsgThread( pParam );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
UINT WINAPI CMazeApp::OutputMsgThread( LPVOID pParam )
{
#define MAX_LOG_LINES 100
TCHAR szLogBuffer[MAX_PATH];
DWORD dwNumProcessed = 0;
while( 1 )
{
// Wait for output to be added to the queue or the quit flag to be set
WaitForSingleObject( m_hOutputMsgEvent, INFINITE );
if( m_bQuitThread )
break;
// Update the time stamp
UpdateTimeStamp();
// Lock output queue
m_OutputMsgQueueLock.Enter();
dwNumProcessed = 0;
// While we have there are messages to print and we
// have display'ed less than 5 messages
while ( m_lQueueSize > 0 && dwNumProcessed < 5 )
{
switch( m_EnumLineType[m_dwNextOutputMsg] )
{
case LINE_LOG:
{
// Add m_szOutputMsgBuffer[m_dwNextOutputMsg] to szLogBuffer array,
// and redisplay the array on the top half of the screen
_stprintf( szLogBuffer, TEXT("%s %s"),
m_strTimeStamp, m_szOutputMsgBuffer[m_dwNextOutputMsg] );
#ifdef _DEBUG
OutputDebugString( szLogBuffer );
OutputDebugString( TEXT("\n") );
#endif
if( m_hLogFile )
{
DWORD dwWritten;
WriteFile( m_hLogFile, szLogBuffer,
lstrlen( szLogBuffer ), &dwWritten, NULL );
TCHAR strEOL = TEXT('\r');
WriteFile( m_hLogFile, &strEOL,
sizeof(TCHAR), &dwWritten, NULL );
strEOL = TEXT('\n');
WriteFile( m_hLogFile, &strEOL,
sizeof(TCHAR), &dwWritten, NULL );
static float s_fLastFlushTime = DXUtil_Timer( TIMER_GETAPPTIME );
float fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
if( fCurTime - s_fLastFlushTime > 0.2f )
{
FlushFileBuffers( m_hLogFile );
s_fLastFlushTime = fCurTime;
}
}
break;
}
default:
_tcscpy( szLogBuffer, m_szOutputMsgBuffer[m_dwNextOutputMsg] );
break;
}
m_pMazeGraphics->HandleOutputMsg( m_EnumLineType[m_dwNextOutputMsg], szLogBuffer );
m_dwNextOutputMsg++;
if( m_dwNextOutputMsg == MAX_OUTPUT_QUEUE )
m_dwNextOutputMsg = 0;
m_lQueueSize--;
dwNumProcessed++;
}
// Unlock output queue
m_OutputMsgQueueLock.Leave();
if( m_hLogFile )
FlushFileBuffers( m_hLogFile );
// Yield time to other threads
Sleep( 10 );
// If there are still messages left, then signal the event
if( m_lQueueSize > 0 )
SetEvent( m_hOutputMsgEvent );
}
if( m_hLogFile )
{
CloseHandle( m_hLogFile );
m_hLogFile = NULL;
}
return 0;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CMazeApp::ConsolePrintf( EnumLineType enumLineType, const TCHAR* fmt, ... )
{
// Format the message into a buffer
TCHAR buffer[512];
_vstprintf( buffer, fmt, (CHAR*) ((&fmt)+1) );
// Lock the output queue
m_OutputMsgQueueLock.Enter();
// Find free spot
if( m_lQueueSize != MAX_OUTPUT_QUEUE )
{
// Format message into the buffer
_vstprintf( m_szOutputMsgBuffer[m_dwNextFreeOutputMsg], fmt, (CHAR*)((&fmt)+1) );
m_EnumLineType[m_dwNextFreeOutputMsg] = enumLineType;
// Increment output pointer and wrap around
m_dwNextFreeOutputMsg++;
if( m_dwNextFreeOutputMsg == MAX_OUTPUT_QUEUE )
m_dwNextFreeOutputMsg = 0;
// Increment message count
m_lQueueSize++;
}
// Unlock output queue
m_OutputMsgQueueLock.Leave();
// Signal event so the output thread empties the queue
SetEvent( m_hOutputMsgEvent );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CMazeApp::UpdateTimeStamp()
{
static float s_fTimeStampUpdateCountdown = -10.0f;
float fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
if( fCurTime - s_fTimeStampUpdateCountdown > 1.0f )
{
SYSTEMTIME sysTime;
GetLocalTime( &sysTime );
_stprintf( m_strTimeStamp, TEXT("[%02d-%02d-%02d %02d:%02d:%02d]"),
sysTime.wMonth, sysTime.wDay, sysTime.wYear % 100,
sysTime.wHour, sysTime.wMinute, sysTime.wSecond );
// Compute how many milliseconds until the next second change
s_fTimeStampUpdateCountdown = fCurTime;
}
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CMazeApp::CreateTempLogFile()
{
BOOL bSuccess;
TCHAR strTempFileName[MAX_PATH];
TCHAR strTime[MAX_PATH];
DWORD dwCount;
GetTempPath( MAX_PATH, m_strLogDir );
lstrcat( m_strLogDir, TEXT("DirectPlayMaze\\") );
// Create the directory if it doesn't exist
if( GetFileAttributes( m_strLogDir ) == -1 )
{
bSuccess = CreateDirectory( m_strLogDir, NULL );
if( !bSuccess )
{
ConsolePrintf( LINE_LOG, TEXT("Could not create create temp directory '%s'"), m_strLogDir );
goto LFail;
}
}
ConsolePrintf( LINE_LOG, TEXT("Log Directory: '%s'"), m_strLogDir );
SYSTEMTIME sysTime;
GetLocalTime( &sysTime );
_stprintf( strTime, TEXT("client-%04d-%02d-%02d-"),
sysTime.wYear, sysTime.wMonth, sysTime.wDay );
dwCount = 0;
while(TRUE)
{
wsprintf( m_strLogFile, TEXT("%s%05d.log"), strTime, dwCount );
lstrcpy( strTempFileName, m_strLogDir );
lstrcat( strTempFileName, m_strLogFile );
DWORD dwResult = GetFileAttributes( strTempFileName );
if( dwResult == -1 )
break;
dwCount++;
}
if( m_hLogFile )
{
CloseHandle( m_hLogFile );
m_hLogFile = NULL;
}
m_hLogFile = CreateFile( strTempFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
if( m_hLogFile == INVALID_HANDLE_VALUE )
{
ConsolePrintf( LINE_LOG, TEXT("Could not create create temp file '%s'"), strTempFileName );
goto LFail;
}
ConsolePrintf( LINE_LOG, TEXT("Logging to temp file: '%s'"), m_strLogFile );
return;
LFail:
ConsolePrintf( LINE_LOG, TEXT("File logging disabled") );
m_Config.bFileLogging = FALSE;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CMazeApp::CloseTempLogFile()
{
CloseHandle( m_hLogFile );
m_hLogFile = NULL;
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CMazeApp::ReadConfig()
{
HKEY hKey = NULL;
RegOpenKeyEx( HKEY_CURRENT_USER, MAZE_REGKEYNAME, 0, KEY_READ, &hKey );
DXUtil_ReadBoolRegKey( hKey, TEXT("ConnectToMicrosoftSite"), &m_Config.bConnectToMicrosoftSite, TRUE );
DXUtil_ReadBoolRegKey( hKey, TEXT("ConnectToLocalServer"), &m_Config.bConnectToLocalServer, FALSE );
DXUtil_ReadBoolRegKey( hKey, TEXT("ConnectToRemoteServer"), &m_Config.bConnectToRemoteServer, FALSE );
DXUtil_ReadIntRegKey( hKey, TEXT("NetworkRetryDelay"), &m_Config.dwNetworkRetryDelay, 30 );
DXUtil_ReadBoolRegKey( hKey, TEXT("FileLogging"), &m_Config.bFileLogging, TRUE );
DXUtil_ReadStringRegKey( hKey, TEXT("IPAddress"), m_Config.szIPAddress, sizeof(m_Config.szIPAddress), TEXT("\0") );
DXUtil_ReadBoolRegKey( hKey, TEXT("ShowFramerate"), &m_Config.bShowFramerate, TRUE );
DXUtil_ReadBoolRegKey( hKey, TEXT("ShowIndicators"), &m_Config.bShowIndicators, TRUE );
DXUtil_ReadBoolRegKey( hKey, TEXT("DrawMiniMap"), &m_Config.bDrawMiniMap, TRUE );
DXUtil_ReadBoolRegKey( hKey, TEXT("FullScreen"), &m_Config.bFullScreen, TRUE );
DXUtil_ReadBoolRegKey( hKey, TEXT("Reflections"), &m_Config.bReflections, FALSE );
DXUtil_ReadBoolRegKey( hKey, TEXT("AutoDisconnnect"), &m_Config.bAutoDisconnnect, FALSE );
DXUtil_ReadBoolRegKey( hKey, TEXT("AutoConnnect"), &m_Config.bAutoConnnect, FALSE );
DXUtil_ReadIntRegKey( hKey, TEXT("LogLevel"), &m_Config.dwLogLevel, 2 );
DXUtil_ReadIntRegKey( hKey, TEXT("AutoPrintStats"), &m_Config.dwAutoPrintStats, 10 );
RegCloseKey( hKey );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void CMazeApp::WriteConfig()
{
HKEY hKey;
DWORD dwDisposition;
if( !m_bSaveSettings )
return;
RegCreateKeyEx( HKEY_CURRENT_USER, MAZE_REGKEYNAME, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
&hKey, &dwDisposition );
DXUtil_WriteBoolRegKey( hKey, TEXT("ConnectToMicrosoftSite"), m_Config.bConnectToMicrosoftSite );
DXUtil_WriteBoolRegKey( hKey, TEXT("ConnectToLocalServer"), m_Config.bConnectToLocalServer );
DXUtil_WriteBoolRegKey( hKey, TEXT("ConnectToRemoteServer"), m_Config.bConnectToRemoteServer );
DXUtil_WriteIntRegKey( hKey, TEXT("NetworkRetryDelay"), m_Config.dwNetworkRetryDelay );
DXUtil_WriteBoolRegKey( hKey, TEXT("FileLogging"), m_Config.bFileLogging );
DXUtil_WriteStringRegKey( hKey, TEXT("IPAddress"), m_Config.szIPAddress );
DXUtil_WriteBoolRegKey( hKey, TEXT("ShowFramerate"), m_Config.bShowFramerate );
DXUtil_WriteBoolRegKey( hKey, TEXT("ShowIndicators"), m_Config.bShowIndicators );
DXUtil_WriteBoolRegKey( hKey, TEXT("DrawMiniMap"), m_Config.bDrawMiniMap );
DXUtil_WriteBoolRegKey( hKey, TEXT("FullScreen"), m_Config.bFullScreen );
DXUtil_WriteBoolRegKey( hKey, TEXT("Reflections"), m_Config.bReflections );
DXUtil_WriteBoolRegKey( hKey, TEXT("AutoDisconnnect"), m_Config.bAutoDisconnnect );
DXUtil_WriteBoolRegKey( hKey, TEXT("AutoConnnect"), m_Config.bAutoConnnect );
DXUtil_WriteIntRegKey( hKey, TEXT("LogLevel"), m_Config.dwLogLevel );
DXUtil_WriteIntRegKey( hKey, TEXT("AutoPrintStats"), m_Config.dwAutoPrintStats );
RegCloseKey( hKey );
}
//-----------------------------------------------------------------------------
// Name:
// Desc:
//-----------------------------------------------------------------------------
void ConsolePrintf( ServerBufferType enumLineType, const TCHAR* fmt , ... )
{
// Format the message into a buffer
TCHAR buffer[512];
_vstprintf( buffer, fmt, (CHAR*) ((&fmt)+1) );
s_pMazeApp->ConsolePrintf( LINE_LOG, buffer );
}