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>
1118 lines
36 KiB
C++
1118 lines
36 KiB
C++
//----------------------------------------------------------------------------
|
|
// File: consolegraphics.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 <math.h>
|
|
#include <mmsystem.h>
|
|
#include <process.h>
|
|
#include <dxerr8.h>
|
|
#include <tchar.h>
|
|
#include <dplay8.h>
|
|
#include "SyncObjects.h"
|
|
#include "DummyConnector.h"
|
|
#include "MazeApp.h"
|
|
#include "IMazeGraphics.h"
|
|
#include "ConsoleGraphics.h"
|
|
|
|
static CConsoleGraphics* s_pGraphics = NULL;
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
CConsoleGraphics::CConsoleGraphics()
|
|
{
|
|
s_pGraphics = this;
|
|
|
|
m_bQuitThread = FALSE;
|
|
m_pMazeApp = NULL;
|
|
m_dwNextOutput = 0;
|
|
m_hStdOut = NULL;
|
|
m_dwNumCmdLines = 11;
|
|
m_dwSeperatorLine = 0;
|
|
m_dwNumLogLines = 0;
|
|
m_dwWindowSizeY = 0;
|
|
m_bLocalLoopback = TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
CConsoleGraphics::~CConsoleGraphics()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID CConsoleGraphics::Init( CMazeApp* pMazeApp, CDPlay8Client* pDP8Client,
|
|
CMazeClient* pMazeClient )
|
|
{
|
|
m_pMazeApp = pMazeApp;
|
|
m_pMazeClient = pMazeClient;
|
|
m_pDP8Client = pDP8Client;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT CConsoleGraphics::Create( HINSTANCE hInstance )
|
|
{
|
|
// Set a console control handler so we can clean
|
|
// up gracefully if we're forcibly shut down
|
|
SetConsoleCtrlHandler( CtrlHandler, TRUE );
|
|
m_hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
|
|
|
|
m_pConfig = m_pMazeApp->GetConfig();
|
|
|
|
if( FALSE == ParseCommandLine() )
|
|
return E_FAIL; // stop the app now
|
|
|
|
if( m_pConfig->bAutoConnnect )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Type 'AUTOCONNECT OFF' to stop automatically connecting upon startup.") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Type 'SETUP' to change current connections settings.") );
|
|
}
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Type 'HELP' for a list of commands.") );
|
|
|
|
// Set up the console
|
|
SetConsoleMode( GetStdHandle(STD_INPUT_HANDLE),
|
|
ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT );
|
|
|
|
m_dwLogBufferNext = 0;
|
|
m_dwCmdBufferNext = 0;
|
|
m_dwLastPrompt = 0;
|
|
m_dwCaretPos = 9;
|
|
m_dwNumProcessed = 0;
|
|
|
|
ZeroMemory( m_szCmdBuffer, sizeof(TCHAR)*MAX_CMD_LINES*256 );
|
|
ZeroMemory( m_szLogBuffer, sizeof(TCHAR)*MAX_LOG_LINES*256 );
|
|
|
|
GetConsoleScreenBufferInfo( m_hStdOut, &m_SavedConsoleInfo );
|
|
|
|
m_dwWindowSizeY = 30;
|
|
m_dwSeperatorLine = m_dwWindowSizeY - m_dwNumCmdLines - 2;
|
|
m_dwNumLogLines = m_dwWindowSizeY - m_dwNumCmdLines - 3;
|
|
|
|
SetupConsole( m_dwWindowSizeY );
|
|
ClearScreen();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
INT CConsoleGraphics::Run()
|
|
{
|
|
BOOL bHaveConnectSettings = m_pConfig->bAutoConnnect;
|
|
|
|
// Allow immediate connect only if we already have the
|
|
// connection settings
|
|
m_pMazeApp->SetAllowConnect( bHaveConnectSettings );
|
|
|
|
// Spin up a thread to record/display the output
|
|
UINT dwPromptThreadID;
|
|
m_hPromptThread = (HANDLE)_beginthreadex( NULL, 0, StaticPromptThread,
|
|
NULL, 0, &dwPromptThreadID );
|
|
|
|
FLOAT fElapsedTime;
|
|
while( !m_bQuitThread )
|
|
{
|
|
fElapsedTime = DXUtil_Timer( TIMER_GETELAPSEDTIME );
|
|
m_pMazeApp->FrameMove( fElapsedTime );
|
|
|
|
// Sleep for a little bit to avoid maxing out CPU
|
|
Sleep( 30 );
|
|
};
|
|
|
|
// Wait for threads to shutdown
|
|
WaitForSingleObject( m_hPromptThread, INFINITE );
|
|
CloseHandle( m_hPromptThread );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void CConsoleGraphics::Shutdown()
|
|
{
|
|
RestoreOldConsoleSettings();
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
WCHAR** CConsoleGraphics::ConvertCommandLineToArgvW( WCHAR* strCommandLine, int* argc )
|
|
{
|
|
WCHAR** argv = new WCHAR*[100];
|
|
WCHAR* wstrTemp;
|
|
WCHAR* wstrLast;
|
|
int i = 0;
|
|
|
|
wstrLast = strCommandLine;
|
|
while( i < 100 )
|
|
{
|
|
argv[i] = new WCHAR[MAX_PATH];
|
|
wcscpy( argv[i], wstrLast );
|
|
wstrTemp = wcschr( argv[i], L' ' );
|
|
if( wstrTemp )
|
|
{
|
|
wstrLast = wstrTemp + 1;
|
|
*wstrTemp = 0;
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
*argc = i + 1;
|
|
return argv;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
BOOL CConsoleGraphics::ParseCommandLine()
|
|
{
|
|
int argc = 0;
|
|
int i;
|
|
WCHAR** argv;
|
|
|
|
argv = ConvertCommandLineToArgvW( GetCommandLineW(), &argc );
|
|
|
|
BOOL bParamFound = FALSE;
|
|
BOOL bContinue = TRUE;
|
|
|
|
for ( i = 1 ; i < argc ; i++ )
|
|
{
|
|
const WCHAR* arg = argv[i];
|
|
|
|
if( arg[0] == L'/' || arg[0] == L'-' )
|
|
{
|
|
if( _wcsicmp( arg+1, L"m" ) == 0 )
|
|
{
|
|
m_pConfig->bConnectToMicrosoftSite = TRUE;
|
|
m_pConfig->bConnectToLocalServer = FALSE;
|
|
m_pConfig->bConnectToRemoteServer = FALSE;
|
|
m_pConfig->dwStressConnect = FALSE;
|
|
|
|
bParamFound = TRUE;
|
|
}
|
|
else if( _wcsicmp( arg+1, L"l" ) == 0 )
|
|
{
|
|
m_pConfig->bConnectToMicrosoftSite = FALSE;
|
|
m_pConfig->bConnectToLocalServer = TRUE;
|
|
m_pConfig->bConnectToRemoteServer = FALSE;
|
|
m_pConfig->dwStressConnect = FALSE;
|
|
|
|
bParamFound = TRUE;
|
|
}
|
|
else if( arg[1] == L'r' || arg[1] == L'R' )
|
|
{
|
|
m_pConfig->bConnectToMicrosoftSite = FALSE;
|
|
m_pConfig->bConnectToLocalServer = FALSE;
|
|
m_pConfig->bConnectToRemoteServer = TRUE;
|
|
m_pConfig->dwStressConnect = FALSE;
|
|
|
|
bParamFound = TRUE;
|
|
|
|
if( arg[2] == L':' )
|
|
{
|
|
DXUtil_ConvertWideStringToGeneric( m_pConfig->szIPAddress, arg+3 );
|
|
}
|
|
}
|
|
else if( _wcsnicmp( arg+1, L"SPThreads:", 8 ) == 0 )
|
|
{
|
|
// Points to the number of SP threads the user wants to use.
|
|
m_pConfig->dwSPThreads = _wtoi( arg+11 );
|
|
bParamFound = TRUE;
|
|
|
|
if(m_pConfig->dwSPThreads > MAX_SP_THREADS || m_pConfig->dwSPThreads < MIN_SP_THREADS)
|
|
{
|
|
printf( "Invalid SPThreads Value \n" );
|
|
printf( " SPThreads Value must be between %i and %i.\n",MIN_SP_THREADS, MAX_SP_THREADS);
|
|
printf( " Format: MazeConsoleClient.exe [/SPThreads:n] : Sets number of SP Threads to n \n\n" );
|
|
|
|
bContinue = FALSE;
|
|
}
|
|
}
|
|
else if( _wcsnicmp( arg+1, L"SPBuffer:", 8 ) == 0 )
|
|
{
|
|
// Points to the size of the SP Buffer user wants to use.
|
|
DWORD spBufferSize = _wtoi( arg+10 );
|
|
bParamFound = TRUE;
|
|
|
|
if( spBufferSize > MAX_SP_BUFFER )
|
|
{
|
|
printf( "Invalid SPBuffer Value \n" );
|
|
printf( " SPBuffer Value must be between 0 and %i.\n", MAX_SP_BUFFER);
|
|
printf( " Format: MazeConsoleClient.exe [/SPBuffer:n] : Sets SP Buffer Size to n \n\n" );
|
|
|
|
bContinue = FALSE;
|
|
}
|
|
|
|
// Wait to assign since our buffer size is initialized to f's
|
|
m_pConfig->dwSPBufferSize = spBufferSize;
|
|
|
|
}
|
|
else if( _wcsnicmp( arg+1, L"StressConnect:", 7 ) == 0 )
|
|
{
|
|
m_pConfig->bConnectToMicrosoftSite = FALSE;
|
|
m_pConfig->bConnectToLocalServer = FALSE;
|
|
m_pConfig->bConnectToRemoteServer = FALSE;
|
|
|
|
// Points to the first connection attempt.
|
|
m_pConfig->dwStressConnect = 1;
|
|
bParamFound = TRUE;
|
|
|
|
if( arg[14] == L':' )
|
|
{
|
|
DXUtil_ConvertWideStringToGeneric( m_pConfig->szIPAddress, arg+15 );
|
|
}
|
|
}
|
|
else if( _wcsicmp( arg+1, L"d" ) == 0 ||
|
|
_wcsicmp( arg+1, L"d+" ) == 0 )
|
|
{
|
|
m_pConfig->bAutoDisconnnect = TRUE;
|
|
bParamFound = TRUE;
|
|
}
|
|
else if( _wcsicmp( arg+1, L"d-" ) == 0 )
|
|
{
|
|
m_pConfig->bAutoDisconnnect = FALSE;
|
|
bParamFound = TRUE;
|
|
}
|
|
if( _wcsicmp( arg+1, L"f" ) == 0 ||
|
|
_wcsicmp( arg+1, L"f+" ) == 0 )
|
|
{
|
|
m_pConfig->bFileLogging = TRUE;
|
|
bParamFound = TRUE;
|
|
}
|
|
else if( _wcsicmp( arg+1, L"f-" ) == 0 )
|
|
{
|
|
m_pConfig->bFileLogging = FALSE;
|
|
bParamFound = TRUE;
|
|
}
|
|
else if( _wcsnicmp( arg+1, L"log:", 2 ) == 0 )
|
|
{
|
|
m_pConfig->dwLogLevel = _wtoi( arg+5 );
|
|
bParamFound = TRUE;
|
|
}
|
|
else if( _wcsicmp( arg+1, L"?" ) == 0 )
|
|
{
|
|
printf( "MazeConsoleClient\n" );
|
|
printf( " Format: MazeConsoleClient.exe [/M] [/L] [/R[:ipaddress]] [/D] [/F] [/LOG]\n" );
|
|
printf( "\n" );
|
|
printf( " Options:\n" );
|
|
printf( " /M : connects to Microsoft server\n" );
|
|
printf( " /L : connects to local server\n" );
|
|
printf( " /R[:ipaddress] : connects to remote server at [ipaddress]\n" );
|
|
printf( " /D+ : turns on auto-disconnecting\n" );
|
|
printf( " /D- : turns off auto-disconnecting\n" );
|
|
printf( " /F+ : turns on file logging\n" );
|
|
printf( " /F- : turns off file logging\n" );
|
|
printf( " /Log:n : sets the log level to n\n" );
|
|
printf( " /SPThreads:n : SP threads to n. Range %d - %d\n", MIN_SP_THREADS, MAX_SP_THREADS );
|
|
printf( " /SPBuffer:n : SP buffer size to n. Range 0 - %d\n", MAX_SP_BUFFER );
|
|
printf( " /StressConnect[:ipaddress] : tries [ipaddress], then local server.\n" );
|
|
printf( "\n" );
|
|
printf( " Examples: \n" );
|
|
printf( " MazeConsoleClient /F /LOG:1\n" );
|
|
printf( " MazeConsoleClient /M /D+\n" );
|
|
printf( " MazeConsoleClient /R:myserver.myip.com /F-\n" );
|
|
|
|
bContinue = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bParamFound )
|
|
{
|
|
m_pConfig->bAutoConnnect = TRUE;
|
|
m_pMazeApp->SetSaveSettings( FALSE );
|
|
}
|
|
|
|
for ( i = 1 ; i < argc ; i++ )
|
|
{
|
|
SAFE_DELETE_ARRAY( argv[i] );
|
|
}
|
|
SAFE_DELETE_ARRAY( argv );
|
|
|
|
return bContinue;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
BOOL WINAPI CConsoleGraphics::CtrlHandler( DWORD type )
|
|
{
|
|
switch ( type )
|
|
{
|
|
case CTRL_C_EVENT:
|
|
case CTRL_BREAK_EVENT:
|
|
case CTRL_CLOSE_EVENT:
|
|
case CTRL_LOGOFF_EVENT:
|
|
case CTRL_SHUTDOWN_EVENT:
|
|
// Signal thread to quit
|
|
FreeConsole();
|
|
s_pGraphics->m_bQuitThread = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID CConsoleGraphics::HandleOutputMsg( EnumLineType enumLineType, TCHAR* strLine )
|
|
{
|
|
DWORD i;
|
|
DWORD dwCoordY;
|
|
|
|
switch( enumLineType )
|
|
{
|
|
case LINE_LOG:
|
|
{
|
|
_tcscpy( m_szLogBuffer[m_dwLogBufferNext], strLine );
|
|
|
|
m_dwLogBufferNext++;
|
|
m_dwLogBufferNext %= m_dwNumLogLines;
|
|
dwCoordY = 0;
|
|
|
|
for( i=m_dwLogBufferNext; i<m_dwNumLogLines; i++ )
|
|
{
|
|
dwCoordY++;
|
|
WriteLine( dwCoordY, m_szLogBuffer[i] );
|
|
}
|
|
|
|
for( i=0; i<m_dwLogBufferNext; i++ )
|
|
{
|
|
dwCoordY++;
|
|
WriteLine( dwCoordY, m_szLogBuffer[i] );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case LINE_PROMPT:
|
|
case LINE_CMD:
|
|
{
|
|
// Add m_szOutputBuffer[m_dwNextOutput] to szCmdBuffer array,
|
|
// and redisplay the array on the top half of the screen
|
|
_tcscpy( m_szCmdBuffer[m_dwCmdBufferNext], strLine );
|
|
|
|
#ifdef _DEBUG
|
|
if( enumLineType != LINE_PROMPT )
|
|
{
|
|
OutputDebugString( m_szCmdBuffer[m_dwCmdBufferNext] );
|
|
OutputDebugString( TEXT("\n") );
|
|
}
|
|
#endif
|
|
|
|
if( enumLineType == LINE_PROMPT )
|
|
{
|
|
m_dwLastPrompt = m_dwCmdBufferNext;
|
|
m_dwCaretPos = _tcslen( m_szCmdBuffer[m_dwCmdBufferNext] );
|
|
}
|
|
|
|
m_dwCmdBufferNext++;
|
|
m_dwCmdBufferNext %= m_dwNumCmdLines;
|
|
dwCoordY = m_dwSeperatorLine;
|
|
|
|
for( i=m_dwCmdBufferNext; i<m_dwNumCmdLines; i++ )
|
|
{
|
|
dwCoordY++;
|
|
WriteLine( dwCoordY, m_szCmdBuffer[i] );
|
|
}
|
|
|
|
for( i=0; i<m_dwCmdBufferNext; i++ )
|
|
{
|
|
dwCoordY++;
|
|
WriteLine( dwCoordY, m_szCmdBuffer[i] );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case LINE_INPUT:
|
|
{
|
|
// Update the last prompt line in the szCmdBuffer array with this
|
|
// string of input, so what was typed in is displayed as it scrolls
|
|
_tcscpy( &m_szCmdBuffer[m_dwLastPrompt][m_dwCaretPos], strLine );
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( enumLineType == LINE_PROMPT )
|
|
{
|
|
// Reset the cursor position if this is a cmd prompt line
|
|
COORD coord = { (WORD)m_dwCaretPos, (WORD)m_dwWindowSizeY-2 };
|
|
SetConsoleCursorPosition( m_hStdOut, coord );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID CConsoleGraphics::SetupConsole( DWORD dwWindowSizeY )
|
|
{
|
|
static TCHAR strEmpty[255] = TEXT(" ");
|
|
DWORD dwWritten;
|
|
COORD coord = { 0, 0 };
|
|
SMALL_RECT rcWindow = { 0, 0, 79, (WORD)dwWindowSizeY-1 };
|
|
|
|
SetConsoleWindowInfo( m_hStdOut, TRUE, &rcWindow );
|
|
|
|
COORD crdBufferSize;
|
|
crdBufferSize.X = 80;
|
|
crdBufferSize.Y = (WORD)dwWindowSizeY;
|
|
SetConsoleScreenBufferSize( m_hStdOut, crdBufferSize );
|
|
|
|
// Write a blank string first
|
|
for( int i=rcWindow.Top; i<rcWindow.Bottom; i++ )
|
|
{
|
|
coord.Y = (WORD)i;
|
|
SetConsoleCursorPosition( m_hStdOut, coord );
|
|
WriteConsole( m_hStdOut, strEmpty, rcWindow.Right + 1, &dwWritten, NULL );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID CConsoleGraphics::RestoreOldConsoleSettings()
|
|
{
|
|
static TCHAR strEmpty[255] = TEXT(" ");
|
|
DWORD dwWritten;
|
|
COORD coord = { 0, 0 };
|
|
|
|
SetConsoleScreenBufferSize( m_hStdOut, m_SavedConsoleInfo.dwSize );
|
|
SetConsoleWindowInfo( m_hStdOut, TRUE, &m_SavedConsoleInfo.srWindow );
|
|
|
|
// Write a blank string first
|
|
for( int i=m_SavedConsoleInfo.srWindow.Top;
|
|
i<m_SavedConsoleInfo.srWindow.Bottom;
|
|
i++ )
|
|
{
|
|
coord.Y = (WORD)i;
|
|
SetConsoleCursorPosition( m_hStdOut, coord );
|
|
WriteConsole( m_hStdOut, strEmpty, m_SavedConsoleInfo.srWindow.Right + 1, &dwWritten, NULL );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
VOID CConsoleGraphics::WriteLine( DWORD nCoordY, TCHAR* strBuffer )
|
|
{
|
|
// Write blanks to make all strings 80 TCHARs long so that
|
|
// the old text is erased as this one is displayed
|
|
for( DWORD dwIndex = _tcslen(strBuffer); dwIndex<80; dwIndex++ )
|
|
strBuffer[dwIndex] = ' ';
|
|
strBuffer[dwIndex] = 0;
|
|
|
|
// Write strBuffer at (0,nCoordY)
|
|
DWORD dwWritten;
|
|
COORD coord = { 0, (WORD) nCoordY };
|
|
WriteConsoleOutputCharacter( m_hStdOut, strBuffer, 80, coord, &dwWritten );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void CConsoleGraphics::PrintHelp()
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Commands:") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" SETUP, EXIT, LOGLEVEL, CONNECTIONINFO") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" FILELOG, CONNECT, DISCONNECT") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" AUTOCONNECT, AUTODISCONNECT") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" SETSTATRATE, SETRETRYDELAY") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" SPTHREADS, SPBUFFER") );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void CConsoleGraphics::ClearScreen()
|
|
{
|
|
static TCHAR strEmpty[255] = TEXT(" ");
|
|
DWORD dwWritten;
|
|
DWORD i;
|
|
COORD coord = { 0, 0 };
|
|
DWORD dwCoordY;
|
|
|
|
// Write a blank string first
|
|
for( i=0; i<m_dwWindowSizeY; i++ )
|
|
{
|
|
coord.Y = (WORD)i;
|
|
SetConsoleCursorPosition( m_hStdOut, coord );
|
|
WriteConsole( m_hStdOut, strEmpty, m_SavedConsoleInfo.srWindow.Right + 1, &dwWritten, NULL );
|
|
}
|
|
|
|
// Display a seperator between the two areas of the console window
|
|
TCHAR strBuffer[200];
|
|
_tcscpy( strBuffer, TEXT("-------------------------------------------------------------------------------") );
|
|
WriteLine( m_dwSeperatorLine, strBuffer );
|
|
|
|
dwCoordY = 0;
|
|
for( i=m_dwLogBufferNext; i<m_dwNumLogLines; i++ )
|
|
{
|
|
dwCoordY++;
|
|
WriteLine( dwCoordY, m_szLogBuffer[i] );
|
|
}
|
|
|
|
for( i=0; i<m_dwLogBufferNext; i++ )
|
|
{
|
|
dwCoordY++;
|
|
WriteLine( dwCoordY, m_szLogBuffer[i] );
|
|
}
|
|
|
|
dwCoordY = m_dwSeperatorLine;
|
|
|
|
for( i=m_dwCmdBufferNext; i<m_dwNumCmdLines; i++ )
|
|
{
|
|
dwCoordY++;
|
|
WriteLine( dwCoordY, m_szCmdBuffer[i] );
|
|
}
|
|
|
|
for( i=0; i<m_dwCmdBufferNext; i++ )
|
|
{
|
|
dwCoordY++;
|
|
WriteLine( dwCoordY, m_szCmdBuffer[i] );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void CConsoleGraphics::DoPrompt( TCHAR* strPromptString, TCHAR* strBuffer )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_PROMPT, strPromptString );
|
|
DWORD dwRead;
|
|
BOOL bSuccess;
|
|
bSuccess = ReadConsole( GetStdHandle(STD_INPUT_HANDLE), strBuffer, 128, &dwRead, NULL );
|
|
|
|
if( !bSuccess || dwRead < 2 )
|
|
{
|
|
_tcscpy( strBuffer, TEXT("") );
|
|
return;
|
|
}
|
|
|
|
strBuffer[dwRead-2]=0;
|
|
m_pMazeApp->ConsolePrintf( LINE_INPUT, strBuffer );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void CConsoleGraphics::RunSetupWizard()
|
|
{
|
|
BOOL bWrongToken;
|
|
TCHAR buffer[512];
|
|
|
|
m_pConfig->bConnectToMicrosoftSite = FALSE;
|
|
m_pConfig->bConnectToLocalServer = FALSE;
|
|
m_pConfig->bConnectToRemoteServer = FALSE;
|
|
|
|
bWrongToken = TRUE;
|
|
while( bWrongToken )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Do you want to connect to DirectPlayMaze.rte.microsoft.com? (YES/NO)") );
|
|
DoPrompt( TEXT("(Default:YES) > "), buffer );
|
|
|
|
TCHAR* token = _tcstok( buffer, TEXT(" \t") );
|
|
if( token != NULL )
|
|
{
|
|
_tcsupr( token );
|
|
if( !_tcscmp( token, TEXT("Y") ) || !_tcscmp( token, TEXT("YES") ) )
|
|
{
|
|
m_pConfig->bConnectToMicrosoftSite = TRUE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
else if( !_tcscmp( token, TEXT("N") ) || !_tcscmp( token, TEXT("NO") ) )
|
|
{
|
|
bWrongToken = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pConfig->bConnectToMicrosoftSite = TRUE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
}
|
|
|
|
if( m_pConfig->bConnectToMicrosoftSite == FALSE )
|
|
{
|
|
bWrongToken = TRUE;
|
|
while( bWrongToken )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Do you want to connect to a local server (searches local subnet)? (YES/NO)") );
|
|
DoPrompt( TEXT("(Default:YES) > "), buffer );
|
|
|
|
TCHAR* token = _tcstok( buffer, TEXT(" \t") );
|
|
if( token != NULL )
|
|
{
|
|
_tcsupr( token );
|
|
if( !_tcscmp( token, TEXT("Y") ) || !_tcscmp( token, TEXT("YES") ) )
|
|
{
|
|
m_pConfig->bConnectToLocalServer = TRUE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
else if( !_tcscmp( token, TEXT("N") ) || !_tcscmp( token, TEXT("NO") ) )
|
|
{
|
|
bWrongToken = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pConfig->bConnectToLocalServer = TRUE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
}
|
|
|
|
if( m_pConfig->bConnectToLocalServer == FALSE )
|
|
{
|
|
bWrongToken = TRUE;
|
|
while( bWrongToken )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("What IP address do you want to connect to? ") );
|
|
DoPrompt( TEXT("> "), buffer );
|
|
|
|
TCHAR* token = _tcstok( buffer, TEXT(" \t") );
|
|
if( token != NULL )
|
|
{
|
|
_tcscpy( m_pConfig->szIPAddress, token );
|
|
m_pConfig->bConnectToRemoteServer = TRUE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bWrongToken = TRUE;
|
|
while( bWrongToken )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Turn file logging on? (YES/NO)") );
|
|
DoPrompt( TEXT("(Default:YES) > "), buffer );
|
|
|
|
TCHAR* token = _tcstok( buffer, TEXT(" \t") );
|
|
if( token != NULL )
|
|
{
|
|
_tcsupr( token );
|
|
if( !_tcscmp( token, TEXT("Y") ) || !_tcscmp( token, TEXT("YES") ) )
|
|
{
|
|
m_pConfig->bFileLogging = TRUE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
else if( !_tcscmp( token, TEXT("N") ) || !_tcscmp( token, TEXT("NO") ) )
|
|
{
|
|
m_pConfig->bFileLogging = FALSE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pConfig->bFileLogging = TRUE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
}
|
|
|
|
bWrongToken = TRUE;
|
|
while( bWrongToken )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Use these settings when disconnected and when the app starts? (YES/NO)") );
|
|
DoPrompt( TEXT("(Default:YES) > "), buffer );
|
|
|
|
TCHAR* token = _tcstok( buffer, TEXT(" \t") );
|
|
if( token != NULL )
|
|
{
|
|
_tcsupr( token );
|
|
if( !_tcscmp( token, TEXT("Y") ) || !_tcscmp( token, TEXT("YES") ) )
|
|
{
|
|
m_pConfig->bAutoConnnect = TRUE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
else if( !_tcscmp( token, TEXT("N") ) || !_tcscmp( token, TEXT("NO") ) )
|
|
{
|
|
m_pConfig->bAutoConnnect = FALSE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pConfig->bAutoConnnect = TRUE;
|
|
bWrongToken = FALSE;
|
|
}
|
|
}
|
|
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Type 'SETUP' anytime to change these connections settings.") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Type 'HELP' for a list of commands.") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("") );
|
|
|
|
m_pMazeApp->SetSaveSettings( TRUE );
|
|
m_pMazeApp->WriteConfig();
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
void CConsoleGraphics::ParseInput( TCHAR* buffer )
|
|
{
|
|
// Strip first token from the buffer and pull to upper case
|
|
TCHAR* token = _tcstok( buffer, TEXT(" \t") );
|
|
if( token == NULL )
|
|
return;
|
|
|
|
_tcsupr( token );
|
|
|
|
// See what it is and act accordingly
|
|
if( !_tcscmp( token, TEXT("STOP") ) ||
|
|
!_tcscmp( token, TEXT("QUIT") ) ||
|
|
!_tcscmp( token, TEXT("EXIT") ) )
|
|
{
|
|
m_bQuitThread = TRUE;
|
|
}
|
|
else if( !_tcscmp( token, TEXT("CONNECT") ) )
|
|
{
|
|
m_pMazeApp->SetConnectNow( TRUE );
|
|
}
|
|
else if( !_tcscmp( token, TEXT("DISCONNECT") ) )
|
|
{
|
|
m_pMazeApp->SetDisconnectNow( TRUE );
|
|
}
|
|
else if( !_tcscmp( token, TEXT("AUTOCONNECT") ) )
|
|
{
|
|
token = _tcstok( NULL, TEXT(" \t") );
|
|
if( token )
|
|
{
|
|
_tcsupr( token );
|
|
if( !_tcscmp( token, TEXT("ON") ) )
|
|
m_pConfig->bAutoConnnect = TRUE;
|
|
else if( !_tcscmp( token, TEXT("OFF") ) )
|
|
m_pConfig->bAutoConnnect = FALSE;
|
|
m_pMazeApp->WriteConfig();
|
|
}
|
|
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Auto-Connect set to %s"), (m_pConfig->bAutoConnnect) ? TEXT("ON") : TEXT("OFF") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" If ON, MazeConsoleClient connects automatically reconnects") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" when disconnected, and connects when loading app.") );
|
|
}
|
|
else if( !_tcscmp( token, TEXT("SETRETRYDELAY") ) )
|
|
{
|
|
token = _tcstok( NULL, TEXT(" \t") );
|
|
if( token )
|
|
{
|
|
DWORD dwDelay = _ttol( token );
|
|
if( m_pConfig->dwNetworkRetryDelay < 1 || m_pConfig->dwNetworkRetryDelay > 300 )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Must enter a value between 1 and 300") );
|
|
}
|
|
else
|
|
{
|
|
m_pConfig->dwNetworkRetryDelay = dwDelay;
|
|
}
|
|
}
|
|
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Retry Delay set to %d"), m_pConfig->dwNetworkRetryDelay );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" Sets how long the app waits between attempts to connect to the server.") );
|
|
}
|
|
else if( !_tcscmp( token, TEXT("LOGLEVEL") ) )
|
|
{
|
|
token = _tcstok( NULL, TEXT(" \t") );
|
|
if( token )
|
|
{
|
|
DWORD dwLevel = _ttol( token );
|
|
if( dwLevel > 3 )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Must enter a value between 0 and 3") );
|
|
}
|
|
else
|
|
{
|
|
m_pConfig->dwLogLevel = dwLevel;
|
|
}
|
|
}
|
|
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Log level set to %d"), m_pConfig->dwLogLevel );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" Level 1: No client position ") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" Level 2: Client position every 10 seconds") );
|
|
}
|
|
else if( !_tcscmp( token, TEXT("SETSTATRATE") ) )
|
|
{
|
|
token = _tcstok( NULL, TEXT(" \t") );
|
|
if( token )
|
|
{
|
|
DWORD dwLevel = _ttol( token );
|
|
m_pConfig->dwAutoPrintStats = dwLevel;
|
|
}
|
|
|
|
if( m_pConfig->dwAutoPrintStats != 0 )
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Auto-displaying stats every %d mins"), m_pConfig->dwAutoPrintStats );
|
|
else
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Not auto-displaying stats") );
|
|
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" Controls how often the connection stats are auto-displayed") );
|
|
}
|
|
else if( !_tcscmp( token, TEXT("SETUP") ) )
|
|
{
|
|
m_pMazeApp->SetAllowConnect( FALSE );
|
|
m_pMazeApp->SetDisconnectNow( TRUE );
|
|
RunSetupWizard();
|
|
|
|
if( m_pConfig->bFileLogging )
|
|
m_pMazeApp->CreateTempLogFile();
|
|
else
|
|
m_pMazeApp->CloseTempLogFile();
|
|
|
|
m_pMazeApp->SetConnectNow( TRUE );
|
|
m_pMazeApp->SetAllowConnect( TRUE );
|
|
}
|
|
else if( !_tcscmp( token, TEXT("FILELOG") ) )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Log Directory: '%s'"), m_pMazeApp->GetLogDir() );
|
|
m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Logging to temp file: '%s'"), m_pMazeApp->GetLogFile() );
|
|
}
|
|
else if( !_tcscmp( token, TEXT("AUTODISCONNECT") ) )
|
|
{
|
|
token = _tcstok( NULL, TEXT(" \t") );
|
|
if( token )
|
|
{
|
|
_tcsupr( token );
|
|
if( !_tcscmp( token, TEXT("ON") ) )
|
|
m_pConfig->bAutoDisconnnect = TRUE;
|
|
else if( !_tcscmp( token, TEXT("OFF") ) )
|
|
m_pConfig->bAutoDisconnnect = FALSE;
|
|
m_pMazeApp->WriteConfig();
|
|
}
|
|
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Auto-Disconnect set to %s"), (m_pConfig->bAutoDisconnnect) ? TEXT("ON") : TEXT("OFF") );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT(" If ON, app disconnects randomly") );
|
|
}
|
|
else if( !_tcscmp( token, TEXT("CONNECTIONINFO") ) || !_tcscmp( token, TEXT("CI") ) )
|
|
{
|
|
TCHAR strInfo[5000];
|
|
TCHAR* strEndOfLine;
|
|
TCHAR* strStartOfLine;
|
|
|
|
// Query the IOutboudNet for info about the connection to this user
|
|
m_pDP8Client->GetConnectionInfo( strInfo );
|
|
|
|
m_pMazeApp->ConsolePrintf( LINE_LOG, TEXT("Displaying connection info for 0x%0.8x"), m_pMazeClient->GetLocalClientID() );
|
|
m_pMazeApp->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;
|
|
m_pMazeApp->ConsolePrintf( LINE_LOG, strStartOfLine );
|
|
strStartOfLine = strEndOfLine + 1;
|
|
}
|
|
}
|
|
else if( !_tcscmp( token, TEXT("SPTHREADS") ) || !_tcscmp( token, TEXT("SPT") ) )
|
|
{
|
|
DWORD currentthreads = m_pDP8Client->GetNumSPThreads();
|
|
|
|
token = _tcstok( NULL, TEXT(" \t") );
|
|
if( token )
|
|
{
|
|
DWORD threads = _ttol( token );
|
|
if( (threads > MAX_SP_THREADS) || (threads <= currentthreads) )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Must enter a value between %d and %d"),
|
|
currentthreads, MAX_SP_THREADS );
|
|
}
|
|
else
|
|
{
|
|
m_pDP8Client->SetNumSPThreads( threads );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("SP Threads Set to %d"), threads );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("SP Threads set to %d"),
|
|
m_pDP8Client->GetNumSPThreads() );
|
|
}
|
|
}
|
|
else if( !_tcscmp( token, TEXT("SPBUFFER") ) || !_tcscmp( token, TEXT("SPB") ) )
|
|
{
|
|
token = _tcstok( NULL, TEXT(" \t") );
|
|
if( token )
|
|
{
|
|
DWORD buffer = _ttol( token );
|
|
if( (buffer > MAX_SP_BUFFER) )
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Must enter a value between 0 and %d"),
|
|
MAX_SP_BUFFER );
|
|
}
|
|
else
|
|
{
|
|
m_pDP8Client->SetSPBuffer( buffer );
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("SP Buffer Size Set to %d"),
|
|
m_pDP8Client->GetSPBuffer() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("SP Buffer Size set to %d"),
|
|
m_pDP8Client->GetSPBuffer() );
|
|
}
|
|
}
|
|
else if( !_tcscmp( token, TEXT("HELP") ) || !_tcscmp( token, TEXT("?") ) )
|
|
{
|
|
PrintHelp();
|
|
}
|
|
else if( !_tcscmp( token, TEXT("CLS") ) )
|
|
{
|
|
ClearScreen();
|
|
}
|
|
else
|
|
{
|
|
m_pMazeApp->ConsolePrintf( LINE_CMD, TEXT("Unknown command. Type HELP for list of commands") );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
UINT WINAPI CConsoleGraphics::StaticPromptThread( LPVOID pParam )
|
|
{
|
|
return s_pGraphics->PromptThread( pParam );
|
|
}
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
UINT WINAPI CConsoleGraphics::PromptThread( LPVOID pParam )
|
|
{
|
|
BOOL bHaveConnectSettings = m_pConfig->bAutoConnnect;
|
|
|
|
// Loop around getting and dealing with keyboard input
|
|
TCHAR buffer[512];
|
|
while( !m_bQuitThread )
|
|
{
|
|
if( !bHaveConnectSettings )
|
|
{
|
|
// If we don't have the connection settings yet,
|
|
// then prompt for where to connect to
|
|
RunSetupWizard();
|
|
|
|
if( m_pConfig->bFileLogging )
|
|
m_pMazeApp->CreateTempLogFile();
|
|
else
|
|
m_pMazeApp->CloseTempLogFile();
|
|
|
|
m_pMazeApp->SetAllowConnect( TRUE );
|
|
bHaveConnectSettings = TRUE;
|
|
}
|
|
else
|
|
{
|
|
DoPrompt( TEXT("Command> "), buffer );
|
|
ParseInput( buffer );
|
|
}
|
|
};
|
|
|
|
_tprintf( TEXT("Stopping...") );
|
|
|
|
return 0;
|
|
}
|