home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Game Programming for Teens / VBGPFT.cdr / DirectX8 / dx8a_sdk.exe / samples / multimedia / directplay / maze / mazeserver / main.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-04  |  32.3 KB  |  994 lines

  1. //----------------------------------------------------------------------------    
  2. // File: main.cpp
  3. //
  4. // Desc: 
  5. //
  6. // Copyright (c) 1999-2000 Microsoft Corp. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #define STRICT
  9. #define D3D_OVERLOADS
  10. #include <windows.h>
  11. #include <d3dx.h>
  12. #include <objbase.h>
  13. #include <process.h>
  14. #include <stdio.h>
  15. #include <math.h>
  16. #include <conio.h>
  17. #include <tchar.h>
  18. #include <DXErr8.h>
  19. #include "DXUtil.h"
  20.  
  21. #include "idpserver.h"
  22. #include "server.h"
  23. #include "Maze.h"
  24. #include "MazeServer.h"
  25. #include "MazeClient.h"
  26.  
  27.  
  28.  
  29.  
  30. //-----------------------------------------------------------------------------
  31. // Defines, and constants
  32. //-----------------------------------------------------------------------------
  33. #define MAX_OUTPUT_QUEUE    512
  34.  
  35.  
  36.  
  37.  
  38. //-----------------------------------------------------------------------------
  39. // Global variables
  40. //-----------------------------------------------------------------------------
  41. CDPlay8Server*      g_pDPlay8Server = NULL;
  42. CMazeServer         g_MazeServer;
  43. CMaze               g_Maze;
  44. HANDLE              g_hOutputThread;
  45. HANDLE              g_hUpdateThread;
  46. volatile BOOL       g_bQuitThread;
  47. HANDLE              g_hOutputEvent;
  48. TCHAR               g_szOutputBuffer[MAX_OUTPUT_QUEUE][256];
  49. CONSOLE_SCREEN_BUFFER_INFO g_SavedConsoleInfo;
  50. EnumBufferType      g_enumBufferType[MAX_OUTPUT_QUEUE];
  51. DWORD               g_dwNextOutput      = 0;
  52. DWORD               g_dwNextFreeOutput  = 0;
  53. DWORD               g_dwQueueSize       = 0;
  54. CCriticalSection    g_OutputQueueLock;
  55. HANDLE              g_hStdOut           = NULL;
  56. DWORD               g_dwNumCmdLines     = 11;
  57. DWORD               g_dwSeperatorLine;
  58. DWORD               g_dwNumLogLines;
  59. DWORD               g_dwWindowSizeY;
  60. BOOL                g_bLocalLoopback    = FALSE;
  61. DWORD               g_dwWidth           = DEFAULT_MAZE_WIDTH;
  62. DWORD               g_dwHeight          = DEFAULT_MAZE_HEIGHT;
  63. TCHAR               g_strTimeStamp[50];
  64. FLOAT               g_fAllInfoRate      = 15.0f;
  65. HANDLE              g_hLogFile          = NULL;
  66. BOOL                g_bFileLogging      = TRUE;  // Change this to turn file logging off
  67.  
  68.  
  69.  
  70.  
  71. //-----------------------------------------------------------------------------
  72. // Function-prototypes
  73. //-----------------------------------------------------------------------------
  74. HRESULT      ParseCommandLine( int argc, TCHAR* argv[] );
  75. BOOL WINAPI  CtrlHandler( DWORD type );
  76. UINT WINAPI  OutputThread( LPVOID pParam );
  77. UINT WINAPI  UpdateThread( LPVOID pParam );
  78. void         ParseInput( TCHAR* pBuffer );
  79. VOID         SetupConsole( DWORD dwWindowSizeY );
  80. VOID         RestoreOldConsoleSettings();
  81. VOID         WriteLine( DWORD nCoordY, TCHAR* strBuffer );
  82. void         ClearScreen();
  83. void         UpdateTimeStamp();
  84. void         CreateTempLogFile();
  85. VOID         SuspendPowerManagement();
  86.  
  87.  
  88.  
  89.  
  90. //-----------------------------------------------------------------------------
  91. // Name: 
  92. // Desc: 
  93. //-----------------------------------------------------------------------------
  94. void __cdecl main( int argc, TCHAR* argv[] )
  95. {
  96.     HRESULT hr;
  97.  
  98.     DXUtil_Timer( TIMER_START );
  99.     srand( (DWORD) (DXUtil_Timer( TIMER_GETABSOLUTETIME ) * UINT_MAX) );
  100.  
  101.     // Tell OS's that have power management to not 
  102.     // sleep, since this app will be using the 
  103.     // network connection and need very little user input
  104.     SuspendPowerManagement();
  105.  
  106.     // Parse any command line options
  107.     if( FAILED( ParseCommandLine( argc, argv ) ) )
  108.         return;
  109.  
  110.     // Initialize COM
  111.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  112.  
  113.     // Create an event object to flag pending output messages
  114.     g_hOutputEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  115.  
  116.     if( g_bFileLogging )
  117.         CreateTempLogFile();
  118.  
  119.     // Initalize maze and server objects
  120.     if( FAILED( hr = g_Maze.Init( g_dwWidth, g_dwHeight, DEFAULT_SEED ) ) )
  121.     {
  122.         DXTRACE_ERR( TEXT("g_Maze.Init"), hr );
  123.         goto LCleanup;
  124.     }
  125.  
  126.     if( FAILED( hr = g_MazeServer.Init( &g_Maze ) ) )
  127.     {
  128.         DXTRACE_ERR( TEXT("g_MazeServer.Init"), hr );
  129.         goto LCleanup;
  130.     }
  131.  
  132.     g_pDPlay8Server = new CDPlay8Server();
  133.     if( g_pDPlay8Server == NULL )
  134.     {
  135.         DXTRACE_ERR( TEXT("new"), E_OUTOFMEMORY );
  136.         goto LCleanup;
  137.     }
  138.     
  139.     // Connect maze server module to DP server
  140.     g_pDPlay8Server->SetServer( &g_MazeServer );
  141.     g_MazeServer.SetOutboundServer( g_pDPlay8Server );
  142.  
  143.     // Set a console control handler so we can clean 
  144.     // up gracefully if we're forcibly shut down
  145.     SetConsoleCtrlHandler( CtrlHandler, TRUE );
  146.     g_hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
  147.  
  148.     // Start up the DP server
  149.     if( FAILED( hr = g_pDPlay8Server->Start() ) )
  150.     {
  151.         DXTRACE_ERR( TEXT("Start"), hr );
  152.         g_pDPlay8Server->Shutdown();
  153.         goto LCleanup;
  154.     }
  155.  
  156.     // Spin up a thread to print server output
  157.     UINT dwOutputThreadID;
  158.     g_hOutputThread = (HANDLE)_beginthreadex( NULL, 0, OutputThread, NULL, 0, &dwOutputThreadID );
  159.  
  160.     // Spin up a thread to update output
  161.     UINT dwUpdateThreadID;
  162.     g_hUpdateThread = (HANDLE)_beginthreadex( NULL, 0, UpdateThread, NULL, 0, &dwUpdateThreadID );
  163.  
  164.     ConsolePrintf( LINE_CMD, TEXT("DirectPlay8 Server started") );
  165.     ConsolePrintf( LINE_CMD, TEXT("Type 'HELP' for a list of commands.") );
  166.  
  167.     // Set up the console
  168.     SetConsoleMode( GetStdHandle(STD_INPUT_HANDLE), 
  169.                     ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT );
  170.  
  171.     // Loop around getting and dealing with keyboard input
  172.     TCHAR buffer[512];
  173.     while( !g_bQuitThread )
  174.     {
  175.         ConsolePrintf( LINE_PROMPT, TEXT("Command> ") );
  176.         DWORD dwRead;
  177.         ReadConsole( GetStdHandle(STD_INPUT_HANDLE), buffer, 128, &dwRead, NULL );
  178.         buffer[dwRead-2]=0;
  179.         ConsolePrintf( LINE_INPUT, buffer );
  180.         ParseInput( buffer );
  181.     };
  182.  
  183.     // Wait for the output thread to exit
  184.     WaitForSingleObject( g_hOutputThread, INFINITE );
  185.     WaitForSingleObject( g_hUpdateThread, INFINITE );
  186.     
  187.     // Shutdown maze and server objects
  188.     g_MazeServer.Shutdown();
  189.     g_Maze.Empty();
  190.  
  191.     // Free event object
  192.     CloseHandle( g_hOutputEvent );
  193.  
  194. LCleanup:
  195.     SAFE_DELETE( g_pDPlay8Server );
  196.  
  197.     _tprintf( TEXT("Done!\n") );
  198.  
  199.     // Uninitialize COM
  200.     CoUninitialize();
  201. }
  202.  
  203.  
  204.  
  205.  
  206. //-----------------------------------------------------------------------------
  207. // Name: 
  208. // Desc: 
  209. //-----------------------------------------------------------------------------
  210. HRESULT ParseCommandLine( int argc, TCHAR* argv[] )
  211. {
  212.     for ( int i = 1 ; i < argc ; i++ )
  213.     {
  214.         const TCHAR* strArg  = argv[i];
  215.         if( strArg[0] == '/' || strArg[0] == '-' )
  216.         {
  217.             if( _tcsicmp( strArg+1, TEXT("size") ) == 0 )
  218.             {
  219.                 if( i + 2 < argc )
  220.                 {
  221.                     const TCHAR* strWidth  = argv[i+1];
  222.                     const TCHAR* strHeight = argv[i+2];
  223.  
  224.                     g_dwWidth  = _ttoi( strWidth );
  225.                     g_dwHeight = _ttoi( strHeight );
  226.                 }
  227.             }
  228.         }
  229.     }
  230.  
  231.     return S_OK;
  232. }
  233.  
  234.  
  235.  
  236.  
  237. //-----------------------------------------------------------------------------
  238. // Name: 
  239. // Desc: 
  240. //-----------------------------------------------------------------------------
  241. void ConsolePrintf( EnumBufferType enumBufferType, const TCHAR* fmt, ... )
  242. {
  243.     // Format the message into a buffer
  244.     TCHAR buffer[512];
  245.     _vstprintf( buffer, fmt, (CHAR*) ((&fmt)+1) );
  246.  
  247.     // Lock the output queue
  248.     g_OutputQueueLock.Enter();
  249.  
  250.     // Find free spot
  251.     if( g_dwQueueSize != MAX_OUTPUT_QUEUE )
  252.     {
  253.         // Format message into the buffer
  254.         _vstprintf( g_szOutputBuffer[g_dwNextFreeOutput], fmt, (CHAR*)((&fmt)+1) );
  255.         g_enumBufferType[g_dwNextFreeOutput] = enumBufferType;
  256.     
  257.         // Increment output pointer and wrap around
  258.         g_dwNextFreeOutput++;
  259.         if( g_dwNextFreeOutput == MAX_OUTPUT_QUEUE )
  260.             g_dwNextFreeOutput = 0;
  261.  
  262.         // Increment message count
  263.         g_dwQueueSize++;
  264.     }
  265.  
  266.     // Unlock output queue
  267.     g_OutputQueueLock.Leave();
  268.  
  269.     // Signal event so the output thread empties the queue
  270.     SetEvent( g_hOutputEvent );
  271. }
  272.  
  273.  
  274.  
  275.  
  276. //-----------------------------------------------------------------------------
  277. // Name: 
  278. // Desc: 
  279. //-----------------------------------------------------------------------------
  280. BOOL WINAPI CtrlHandler( DWORD type )
  281. {
  282.     switch ( type )
  283.     {
  284.         case CTRL_C_EVENT:
  285.         case CTRL_BREAK_EVENT:
  286.         case CTRL_CLOSE_EVENT:
  287.         case CTRL_LOGOFF_EVENT:
  288.         case CTRL_SHUTDOWN_EVENT:
  289.             // Signal thread to quit
  290.             g_bQuitThread = TRUE;
  291.             SetEvent( g_hOutputEvent );
  292.             WaitForSingleObject( g_hOutputThread, INFINITE );
  293.             return TRUE;
  294.     }
  295.  
  296.     return FALSE;
  297. }
  298.  
  299.  
  300.  
  301.  
  302. //-----------------------------------------------------------------------------
  303. // Name: 
  304. // Desc: 
  305. //-----------------------------------------------------------------------------
  306. UINT WINAPI UpdateThread( LPVOID pParam )
  307. {
  308.     while( 1 )
  309.     {
  310.         if( g_bQuitThread )
  311.             break;
  312.  
  313.         FLOAT fTimeLapsed = DXUtil_Timer( TIMER_GETELAPSEDTIME );
  314.         FLOAT fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
  315.         static FLOAT s_fLastAllInfoDisplay = fCurTime;
  316.  
  317.         if( g_fAllInfoRate != 0.0f && fCurTime - s_fLastAllInfoDisplay > g_fAllInfoRate * 60.0f )
  318.         {
  319.             g_MazeServer.DisplayAllInfo();           
  320.             s_fLastAllInfoDisplay = fCurTime;
  321.         }
  322.  
  323.         // Sleep for a little bit to avoid maxing the CPU
  324.         Sleep( 100 );
  325.     }
  326.  
  327.     return 0;
  328. }
  329.  
  330.  
  331.  
  332.  
  333. //-----------------------------------------------------------------------------
  334. // Name: 
  335. // Desc: 
  336. //-----------------------------------------------------------------------------
  337. UINT WINAPI OutputThread( LPVOID pParam )
  338. {
  339. #define MAX_CMD_LINES 100
  340. #define MAX_LOG_LINES 100
  341.  
  342.     DWORD i;
  343.     TCHAR szLogBuffer[MAX_LOG_LINES][256];
  344.     TCHAR szCmdBuffer[MAX_CMD_LINES][256];
  345.     DWORD dwLogBufferNext = 0;
  346.     DWORD dwCmdBufferNext = 0;
  347.     DWORD dwLastPrompt = 0;
  348.     DWORD dwCoordY;
  349.     int   dwCaretPos      = 9;
  350.  
  351.     ZeroMemory( szCmdBuffer, sizeof(TCHAR)*MAX_CMD_LINES*256 );
  352.     ZeroMemory( szLogBuffer, sizeof(TCHAR)*MAX_LOG_LINES*256 );
  353.     CoInitializeEx( NULL, COINIT_MULTITHREADED );
  354.  
  355.     GetConsoleScreenBufferInfo( g_hStdOut, &g_SavedConsoleInfo );
  356.  
  357.     if( g_SavedConsoleInfo.dwMaximumWindowSize.Y > 50 )
  358.         g_dwWindowSizeY = 50;
  359.     else
  360.         g_dwWindowSizeY = g_SavedConsoleInfo.dwMaximumWindowSize.Y;
  361.  
  362.     g_dwSeperatorLine = g_dwWindowSizeY - g_dwNumCmdLines - 2;
  363.     g_dwNumLogLines   = g_dwWindowSizeY - g_dwNumCmdLines - 3;
  364.         
  365.     SetupConsole( g_dwWindowSizeY );
  366.     ClearScreen();
  367.  
  368.     while ( 1 )
  369.     {
  370.         // Wait for output to be added to the queue or the quit flag to be set
  371.         WaitForSingleObject( g_hOutputEvent, INFINITE );
  372.         if( g_bQuitThread )
  373.             break;
  374.  
  375.         UpdateTimeStamp();
  376.  
  377.         // Lock output queue
  378.         g_OutputQueueLock.Enter();
  379.  
  380.         // While there are messages to print
  381.         while ( g_dwQueueSize )
  382.         {
  383.             switch( g_enumBufferType[g_dwNextOutput] )
  384.             {
  385.                 case LINE_LOG:
  386.                 {
  387.                     // Add g_szOutputBuffer[g_dwNextOutput] to szLogBuffer array,
  388.                     // and redisplay the array on the top half of the screen
  389.                     _stprintf( szLogBuffer[dwLogBufferNext], "%s %s", 
  390.                                g_strTimeStamp, g_szOutputBuffer[g_dwNextOutput] );
  391.  
  392. #ifdef _DEBUG
  393.                     OutputDebugString( szLogBuffer[dwLogBufferNext] );
  394.                     OutputDebugString( "\n" );
  395. #endif
  396.                     if( g_hLogFile )
  397.                     {
  398.                         DWORD dwWritten;
  399.                         WriteFile( g_hLogFile, szLogBuffer[dwLogBufferNext], 
  400.                                    lstrlen( szLogBuffer[dwLogBufferNext] ), &dwWritten, NULL );
  401.                         TCHAR strEOL = TEXT('\r');
  402.                         WriteFile( g_hLogFile, &strEOL, 
  403.                                    sizeof(TCHAR), &dwWritten, NULL );
  404.                         strEOL = TEXT('\n');
  405.                         WriteFile( g_hLogFile, &strEOL, 
  406.                                    sizeof(TCHAR), &dwWritten, NULL );
  407.  
  408.                         static float s_fLastFlushTime = DXUtil_Timer( TIMER_GETAPPTIME );
  409.                         float fCurTime = DXUtil_Timer( TIMER_GETAPPTIME );
  410.                         if( fCurTime - s_fLastFlushTime > 0.2f )
  411.                         {
  412.                             FlushFileBuffers( g_hLogFile );
  413.                             s_fLastFlushTime = fCurTime;
  414.                         }
  415.                     }
  416.  
  417.                     dwLogBufferNext++;
  418.                     dwLogBufferNext %= g_dwNumLogLines;
  419.                     dwCoordY = 0;
  420.  
  421.                     for( i=dwLogBufferNext; i<g_dwNumLogLines; i++ )
  422.                     {
  423.                         dwCoordY++;
  424.                         WriteLine( dwCoordY, szLogBuffer[i] );
  425.                     }
  426.  
  427.                     for( i=0; i<dwLogBufferNext; i++ )
  428.                     {
  429.                         dwCoordY++;
  430.                         WriteLine( dwCoordY, szLogBuffer[i] );
  431.                     }
  432.                     break;
  433.                 }
  434.  
  435.                 case LINE_PROMPT:
  436.                 case LINE_CMD:
  437.                 {
  438.                     // Add g_szOutputBuffer[g_dwNextOutput] to szCmdBuffer array,
  439.                     // and redisplay the array on the top half of the screen
  440.                     _tcscpy( szCmdBuffer[dwCmdBufferNext], g_szOutputBuffer[g_dwNextOutput] );
  441.  
  442. #ifdef _DEBUG
  443.                     if( g_enumBufferType[g_dwNextOutput] != LINE_PROMPT )
  444.                     {
  445.                         OutputDebugString( szCmdBuffer[dwCmdBufferNext] );
  446.                         OutputDebugString( "\n" );
  447.                     }
  448. #endif
  449.  
  450.                     if( g_enumBufferType[g_dwNextOutput] == LINE_PROMPT )
  451.                     {
  452.                         dwLastPrompt = dwCmdBufferNext;
  453.                         dwCaretPos = _tcslen( szCmdBuffer[dwCmdBufferNext] );
  454.                     }
  455.  
  456.                     dwCmdBufferNext++;
  457.                     dwCmdBufferNext %= g_dwNumCmdLines;
  458.                     dwCoordY = g_dwSeperatorLine;
  459.  
  460.                     for( i=dwCmdBufferNext; i<g_dwNumCmdLines; i++ )
  461.                     {
  462.                         dwCoordY++;
  463.                         WriteLine( dwCoordY, szCmdBuffer[i] );
  464.                     }
  465.  
  466.                     for( i=0; i<dwCmdBufferNext; i++ )
  467.                     {
  468.                         dwCoordY++;
  469.                         WriteLine( dwCoordY, szCmdBuffer[i] );
  470.                     }
  471.                     break;
  472.                 }
  473.  
  474.                 case LINE_INPUT:
  475.                 {
  476.                     // Update the last prompt line in the szCmdBuffer array with this
  477.                     // string of input, so what was typed in is displayed as it scrolls
  478.                     _tcscpy( &szCmdBuffer[dwLastPrompt][dwCaretPos], g_szOutputBuffer[g_dwNextOutput] );
  479.  
  480. #ifdef _DEBUG
  481.                     OutputDebugString( szCmdBuffer[dwLastPrompt] );
  482.                     OutputDebugString( "\n" );
  483. #endif
  484.                     break;
  485.                 }
  486.             }
  487.  
  488.             if( g_enumBufferType[g_dwNextOutput] == LINE_PROMPT )
  489.             {                 
  490.                 // Reset the cursor position if this is a cmd prompt line
  491.                 COORD coord = { (WORD)dwCaretPos, (WORD)g_dwWindowSizeY-2 };
  492.                 SetConsoleCursorPosition( g_hStdOut, coord );
  493.             }
  494.  
  495.             g_dwNextOutput++;
  496.             if( g_dwNextOutput == MAX_OUTPUT_QUEUE )
  497.                 g_dwNextOutput = 0;
  498.  
  499.             g_dwQueueSize--;
  500.         }
  501.  
  502.         // Unlock output queue
  503.         g_OutputQueueLock.Leave();
  504.  
  505.         if( g_hLogFile )
  506.             FlushFileBuffers( g_hLogFile );
  507.     }
  508.  
  509.     _tprintf( TEXT("Stopping...") );
  510.  
  511.     // Kill server (if we had one)
  512.     if( g_pDPlay8Server )
  513.         g_pDPlay8Server->Shutdown();
  514.  
  515.     RestoreOldConsoleSettings();
  516.  
  517.     if( g_hLogFile )
  518.         CloseHandle( g_hLogFile );
  519.  
  520.     CoUninitialize();
  521.     
  522.     return 0;
  523. }
  524.  
  525.  
  526.  
  527.  
  528. //-----------------------------------------------------------------------------
  529. // Name: 
  530. // Desc: 
  531. //-----------------------------------------------------------------------------
  532. VOID SetupConsole( DWORD dwWindowSizeY )
  533. {
  534.     static TCHAR strEmpty[255] = TEXT("                                                                                                                                                                                                                                                              ");
  535.     DWORD dwWritten;
  536.     COORD coord = { 0, 0 };
  537.     SMALL_RECT rcWindow = { 0, 0, 79, (WORD)dwWindowSizeY-1 };
  538.  
  539.     SetConsoleWindowInfo( g_hStdOut, TRUE, &rcWindow );
  540.  
  541.     COORD crdBufferSize;
  542.     crdBufferSize.X = 80;
  543.     crdBufferSize.Y = (WORD)dwWindowSizeY;
  544.     SetConsoleScreenBufferSize( g_hStdOut, crdBufferSize );
  545.  
  546.     // Write a blank string first
  547.     for( int i=rcWindow.Top; i<rcWindow.Bottom; i++ )
  548.     {
  549.         coord.Y = (WORD)i;
  550.         SetConsoleCursorPosition( g_hStdOut, coord );
  551.         WriteConsole( g_hStdOut, strEmpty, rcWindow.Right + 1, &dwWritten, NULL );
  552.     }
  553. }
  554.  
  555.  
  556.  
  557.  
  558. //-----------------------------------------------------------------------------
  559. // Name: 
  560. // Desc: 
  561. //-----------------------------------------------------------------------------
  562. VOID RestoreOldConsoleSettings()
  563. {
  564.     static TCHAR strEmpty[255] = TEXT("                                                                                                                                                                                                                                                              ");
  565.     DWORD dwWritten;
  566.     COORD coord = { 0, 0 };
  567.  
  568.     SetConsoleScreenBufferSize( g_hStdOut, g_SavedConsoleInfo.dwSize );
  569.     SetConsoleWindowInfo( g_hStdOut, TRUE, &g_SavedConsoleInfo.srWindow );
  570.  
  571.     // Write a blank string first
  572.     for( int i=g_SavedConsoleInfo.srWindow.Top; 
  573.          i<g_SavedConsoleInfo.srWindow.Bottom;
  574.          i++ )
  575.     {
  576.         coord.Y = (WORD)i;
  577.         SetConsoleCursorPosition( g_hStdOut, coord );
  578.         WriteConsole( g_hStdOut, strEmpty, g_SavedConsoleInfo.srWindow.Right + 1, &dwWritten, NULL );
  579.     }
  580. }
  581.  
  582.  
  583.  
  584.  
  585. //-----------------------------------------------------------------------------
  586. // Name: 
  587. // Desc: 
  588. //-----------------------------------------------------------------------------
  589. VOID WriteLine( DWORD nCoordY, TCHAR* strBuffer )
  590. {
  591.     // Write blanks to make all strings 80 TCHARs long so that
  592.     // the old text is erased as this one is displayed
  593.     for( DWORD dwIndex = _tcslen(strBuffer); dwIndex<80; dwIndex++ )
  594.         strBuffer[dwIndex] = ' ';
  595.     strBuffer[dwIndex] = 0;
  596.  
  597.     // Write strBuffer at (0,nCoordY)
  598.     DWORD dwWritten;
  599.     COORD coord = { 0, (WORD) nCoordY };
  600.     WriteConsoleOutputCharacter( g_hStdOut, strBuffer, 80, coord, &dwWritten ); 
  601. }
  602.  
  603.  
  604.  
  605.  
  606. //-----------------------------------------------------------------------------
  607. // Name: 
  608. // Desc: 
  609. //-----------------------------------------------------------------------------
  610. void PrintHelp()
  611. {
  612.     ConsolePrintf( LINE_CMD, TEXT("Commands:") );
  613.     ConsolePrintf( LINE_CMD, TEXT("    STOP, LOGLEVEL, CLIENTUPDATE") );
  614.     ConsolePrintf( LINE_CMD, TEXT("    SERVERRELIABLE, CLIENTRELIABLE") );
  615.     ConsolePrintf( LINE_CMD, TEXT("    SERVERTIMEOUT, CLIENTTIMEOUT") );
  616.     ConsolePrintf( LINE_CMD, TEXT("    CONNECTIONINFO, STATS, ALLINFO, ALLINFORATE") );
  617. }
  618.  
  619.  
  620.  
  621.  
  622. //-----------------------------------------------------------------------------
  623. // Name: 
  624. // Desc: 
  625. //-----------------------------------------------------------------------------
  626. void ClearScreen()
  627. {
  628.     static TCHAR strEmpty[255] = TEXT("                                                                                                                                                                                                                                                              ");
  629.     DWORD dwWritten;
  630.     COORD coord = { 0, 0 };
  631.  
  632.     // Write a blank string first
  633.     for( DWORD i=0; i<g_dwWindowSizeY; i++ )
  634.     {
  635.         coord.Y = (WORD)i;
  636.         SetConsoleCursorPosition( g_hStdOut, coord );
  637.         WriteConsole( g_hStdOut, strEmpty, g_SavedConsoleInfo.srWindow.Right + 1, &dwWritten, NULL );
  638.     }
  639.  
  640.     // Display a seperator between the two areas of the console window
  641.     TCHAR strBuffer[200];
  642.     _tcscpy( strBuffer, TEXT("-------------------------------------------------------------------------------") );
  643.     WriteLine( g_dwSeperatorLine, strBuffer );
  644. }
  645.  
  646.  
  647.  
  648.  
  649. //-----------------------------------------------------------------------------
  650. // Name: 
  651. // Desc: 
  652. //-----------------------------------------------------------------------------
  653. void ParseInput( TCHAR* buffer )
  654. {
  655.     // Strip first token from the buffer and pull to upper case
  656.     TCHAR* token = _tcstok( buffer, TEXT(" \t") );
  657.     if( token == NULL )
  658.         return;
  659.  
  660.     _tcsupr( token );
  661.  
  662.     // See what it is and act accordingly
  663.     if( !_tcscmp( token, TEXT("STATS") ) )
  664.     {
  665.         g_MazeServer.PrintStats();
  666.     }
  667.     else if( !_tcscmp( token, TEXT("STOP") ) || 
  668.              !_tcscmp( token, TEXT("QUIT") ) || 
  669.              !_tcscmp( token, TEXT("EXIT") ) )
  670.     {
  671.         g_bQuitThread = TRUE;
  672.         SetEvent( g_hOutputEvent );
  673.     }
  674.     else if( !_tcscmp( token, TEXT("SERVERRELIABLE") ) || 
  675.              !_tcscmp( token, TEXT("SR") ) )
  676.     {
  677.         token = _tcstok( NULL, TEXT(" \t") );
  678.         if( token )
  679.         {
  680.             DWORD chance = _ttol( token );
  681.             if( chance > 100 )
  682.             {
  683.                 ConsolePrintf( LINE_CMD, TEXT("Must enter a value between 0 and 100") );
  684.             }
  685.             else
  686.             {
  687.                 g_MazeServer.SetServerReliableRate( chance );
  688.                 ConsolePrintf( LINE_CMD, TEXT("Server reliable packet rate set to %d%%"), chance );
  689.             }
  690.         }
  691.         else
  692.         {
  693.             ConsolePrintf( LINE_CMD, TEXT("Server reliable packet rate is %d%%"), 
  694.                           g_MazeServer.GetServerReliableRate() );
  695.         }
  696.     }
  697.     else if( !_tcscmp( token, TEXT("CLIENTRELIABLE") ) || 
  698.               !_tcscmp( token, TEXT("CR") ) )
  699.     {
  700.         token = _tcstok( NULL, TEXT(" \t") );
  701.         if( token )
  702.         {
  703.             DWORD   chance = _ttol( token );
  704.             if( chance > 100 )
  705.             {
  706.                 ConsolePrintf( LINE_CMD, TEXT("Must enter a value between 0 and 100") );
  707.             }
  708.             else
  709.             {
  710.                 g_MazeServer.SetClientReliableRate( chance );
  711.                 ConsolePrintf( LINE_CMD, TEXT("Client reliable packet rate set to %d%%"), chance );
  712.             }
  713.         }
  714.         else
  715.         {
  716.             ConsolePrintf( LINE_CMD, TEXT("Client reliable packet rate is %d%%"), 
  717.                           g_MazeServer.GetClientReliableRate() );
  718.         }
  719.     }
  720.     else if( !_tcscmp( token, TEXT("CLIENTUPDATE") ) || !_tcscmp( token, TEXT("CU") ) )
  721.     {
  722.         token = _tcstok( NULL, TEXT(" \t") );
  723.         if( token )
  724.         {
  725.             DWORD   rate = _ttol( token );
  726.             if( rate > 1500 || rate < 50 )
  727.             {
  728.                 ConsolePrintf( LINE_CMD, TEXT("Must enter a value between 50 and 1500 (milliseconds)") );
  729.             }
  730.             else
  731.             {
  732.                 g_MazeServer.SetClientUpdateRate( rate );
  733.                 ConsolePrintf( LINE_CMD, TEXT("Client update frequency set to %dms"), rate );
  734.             }
  735.         }
  736.         else
  737.         {
  738.             ConsolePrintf( LINE_CMD, TEXT("Client update frequency is %dms"), g_MazeServer.GetClientUpdateRate() );
  739.         }
  740.     }
  741.     else if( !_tcscmp( token, TEXT("SERVERTIMEOUT") ) || !_tcscmp( token, TEXT("ST") ) )
  742.     {
  743.         token = _tcstok( NULL, TEXT(" \t") );
  744.         if( token )
  745.         {
  746.             long timeout = _ttol( token );
  747.             if( timeout > 3000 || timeout < 0 )
  748.             {
  749.                 ConsolePrintf( LINE_CMD, TEXT("Must enter a value between 0 and 3000 (milliseconds) (0 for none)") );
  750.             }
  751.             else
  752.             {
  753.                 g_MazeServer.SetServerTimeout( timeout );
  754.                 if( timeout == 0 )
  755.                     ConsolePrintf( LINE_CMD, TEXT("Server timeout set to 'no timeout'") );
  756.                 else
  757.                     ConsolePrintf( LINE_CMD, TEXT("Server timeout set to %dms"), timeout );
  758.             }
  759.         }
  760.         else
  761.         {
  762.             if( g_MazeServer.GetServerTimeout() == 0 )
  763.                 ConsolePrintf( LINE_CMD, TEXT("Server timeout set to 'no timeout'") );
  764.             else
  765.                 ConsolePrintf( LINE_CMD, TEXT("Server timeout is %dms"), g_MazeServer.GetServerTimeout() );
  766.         }
  767.     }
  768.     else if( !_tcscmp( token, TEXT("CLIENTTIMEOUT") ) || !_tcscmp( token, TEXT("CT") ) )
  769.     {
  770.         token = _tcstok( NULL, TEXT(" \t") );
  771.         if( token )
  772.         {
  773.             long timeout = _ttol( token );
  774.             if( timeout > 3000 || timeout < 0 )
  775.             {
  776.                 ConsolePrintf( LINE_CMD, TEXT("Must enter a value between 0 and 3000 (milliseconds) (0 for none)") );
  777.             }
  778.             else
  779.             {
  780.                 g_MazeServer.SetClientTimeout( timeout );
  781.                 if( timeout == 0 )
  782.                     ConsolePrintf( LINE_CMD, TEXT("Client timeout set to 'no timeout'") );
  783.                 else
  784.                     ConsolePrintf( LINE_CMD, TEXT("Client timeout set to %dms"), timeout );
  785.             }
  786.         }
  787.         else
  788.         {
  789.             if( g_MazeServer.GetClientTimeout() == 0 )
  790.                 ConsolePrintf( LINE_CMD, TEXT("Client timeout set to 'no timeout'") );
  791.             else
  792.                 ConsolePrintf( LINE_CMD, TEXT("Client timeout is %dms"), g_MazeServer.GetClientTimeout() );
  793.         }
  794.     }
  795.     else if( !_tcscmp( token, TEXT("ALLINFORATE") ) || !_tcscmp( token, TEXT("AIRATE") ) )
  796.     {
  797.         token = _tcstok( NULL, TEXT(" \t") );
  798.         if( token )
  799.         {
  800.             g_fAllInfoRate = (float) _ttol( token );
  801.         }
  802.  
  803.         if( g_fAllInfoRate == 0.0f )
  804.             ConsolePrintf( LINE_CMD, TEXT("ALLINFO will not be called automatically") );
  805.         else
  806.             ConsolePrintf( LINE_CMD, TEXT("ALLINFO will be called every %0.0f mins"), g_fAllInfoRate );
  807.         ConsolePrintf( LINE_CMD, TEXT("     Sets how often ALLINFO is automatically called (0 for never)") );
  808.     }
  809.     else if( !_tcscmp( token, TEXT("ALLINFO") ) || !_tcscmp( token, TEXT("AI") ) )
  810.     {
  811.         g_MazeServer.DisplayAllInfo();
  812.     }
  813.     else if( !_tcscmp( token, TEXT("CONNECTIONINFO") ) || !_tcscmp( token, TEXT("CI") ) )
  814.     {
  815.         token = _tcstok( NULL, TEXT(" \t") );
  816.         BOOL bTokenOK = FALSE;
  817.         if( token )
  818.         {
  819.             if( strlen(token) == 8 )
  820.             {
  821.                 DWORD dwID;
  822.                 sscanf( token, "%x", &dwID );
  823.                 g_MazeServer.DisplayConnectionInfo( dwID );
  824.                 bTokenOK = TRUE;
  825.             }
  826.         }
  827.  
  828.         if( !bTokenOK )
  829.         {
  830.             ConsolePrintf( LINE_CMD, TEXT("Must enter the 8 digit client DPNID") );
  831.         }
  832.     }
  833.     else if( !_tcscmp( token, TEXT("LOGLEVEL") ) )
  834.     {
  835.         token = _tcstok( NULL, TEXT(" \t") );
  836.         if( token )
  837.         {
  838.             DWORD dwLevel = _ttol( token );
  839.             if( dwLevel > 3 )
  840.             {
  841.                 ConsolePrintf( LINE_CMD, TEXT("Must enter a value between 0 and 3") );
  842.             }
  843.             else
  844.             {
  845.                 g_MazeServer.SetLogLevel( dwLevel );
  846.             }
  847.         }
  848.  
  849.         ConsolePrintf( LINE_CMD, TEXT("Log level set to %d"), g_MazeServer.GetLogLevel() );
  850.         ConsolePrintf( LINE_CMD, TEXT("     Level 1: Connects and disconnects only") );
  851.         ConsolePrintf( LINE_CMD, TEXT("     Level 2: Client position every 5 seconds") );
  852.         ConsolePrintf( LINE_CMD, TEXT("     Level 3: Show all client position ") );
  853.     }
  854.     else if( !_tcscmp( token, TEXT("HELP") ) || !_tcscmp( token, TEXT("?") ) )
  855.     {
  856.         PrintHelp();
  857.     }
  858.     else if( !_tcscmp( token, TEXT("CLS") ) )
  859.     {
  860.         ClearScreen();
  861.     }
  862.     else
  863.     {
  864.         ConsolePrintf( LINE_CMD, TEXT("Unknown command. Type HELP for list of commands") );
  865.     }
  866. }
  867.  
  868.  
  869.  
  870.  
  871. //-----------------------------------------------------------------------------
  872. // Name: 
  873. // Desc: 
  874. //-----------------------------------------------------------------------------
  875. void UpdateTimeStamp()
  876. {
  877.     SYSTEMTIME sysTime;
  878.     GetLocalTime( &sysTime );
  879.     _stprintf( g_strTimeStamp, TEXT("[%02d-%02d-%02d %02d:%02d:%02d]"),
  880.                sysTime.wMonth, sysTime.wDay, sysTime.wYear % 100, 
  881.                sysTime.wHour, sysTime.wMinute, sysTime.wSecond );
  882. }
  883.     
  884.  
  885.     
  886.  
  887. //-----------------------------------------------------------------------------
  888. // Name: 
  889. // Desc: 
  890. //-----------------------------------------------------------------------------
  891. void CreateTempLogFile()
  892. {
  893.     BOOL bSuccess;
  894.     TCHAR strTempPath[MAX_PATH];
  895.     TCHAR strTempFileName[MAX_PATH];
  896.     TCHAR strBaseName[MAX_PATH];
  897.     TCHAR strTime[MAX_PATH];
  898.     DWORD dwCount;
  899.     
  900.     GetTempPath( MAX_PATH, strTempPath );
  901.     lstrcat( strTempPath, TEXT("DirectPlayMaze\\") );
  902.  
  903.     // Create the directory if it doesn't exist
  904.     if( GetFileAttributes( strTempPath ) == -1 )
  905.     {
  906.         bSuccess = CreateDirectory( strTempPath, NULL );
  907.         if( !bSuccess )
  908.         {
  909.             ConsolePrintf( LINE_LOG, TEXT("Could not create create temp directory '%s'"), strTempPath );
  910.             goto LFail;
  911.         }
  912.     }
  913.  
  914.     ConsolePrintf( LINE_LOG, TEXT("Logging events to temporary file") );
  915.  
  916.     ConsolePrintf( LINE_LOG, TEXT("Log directory:") );
  917.     ConsolePrintf( LINE_LOG, strTempPath );
  918.  
  919.     SYSTEMTIME sysTime;
  920.     GetLocalTime( &sysTime );
  921.     _stprintf( strTime, TEXT("server-%04d-%02d-%02d-"),
  922.                sysTime.wYear, sysTime.wMonth, sysTime.wDay );
  923.  
  924.     dwCount = 0;
  925.  
  926.     while(TRUE)
  927.     {
  928.         wsprintf( strBaseName, "%s%05d.log", strTime, dwCount );
  929.         lstrcpy( strTempFileName, strTempPath );
  930.         lstrcat( strTempFileName, strBaseName );
  931.         DWORD dwResult = GetFileAttributes( strTempFileName );
  932.         if( dwResult == -1 )
  933.             break;
  934.  
  935.         dwCount++;
  936.     }
  937.  
  938.     g_hLogFile = CreateFile( strTempFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
  939.                              CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
  940.     if( g_hLogFile == INVALID_HANDLE_VALUE )
  941.     {
  942.         ConsolePrintf( LINE_LOG, TEXT("Could not create create temp file '%s'"), strTempFileName );
  943.         goto LFail;
  944.     }
  945.  
  946.     ConsolePrintf( LINE_LOG, TEXT("Log file name:") );
  947.     ConsolePrintf( LINE_LOG, strBaseName );
  948.     return;
  949.  
  950. LFail:
  951.     ConsolePrintf( LINE_LOG, TEXT("File logging disabled") );
  952.     g_bFileLogging = FALSE;
  953. }
  954.  
  955.  
  956.  
  957.  
  958. //-----------------------------------------------------------------------------
  959. // Name: 
  960. // Desc: 
  961. //-----------------------------------------------------------------------------
  962. VOID SuspendPowerManagement()
  963. {
  964.     TCHAR szPath[MAX_PATH];
  965.     HINSTANCE hInstKernel32 = NULL;
  966.     typedef EXECUTION_STATE (WINAPI* LPSETTHREADEXECUTIONSTATE)( EXECUTION_STATE esFlags );
  967.     LPSETTHREADEXECUTIONSTATE pSetThreadExecutionState = NULL;
  968.  
  969.     GetSystemDirectory(szPath, MAX_PATH);
  970.  
  971.     // SetThreadExecutionState() isn't availible on some old OS's, 
  972.     // so do a LoadLibrary to get to it.
  973.     lstrcat(szPath, TEXT("\\kernel32.dll"));
  974.     hInstKernel32 = LoadLibrary(szPath);
  975.  
  976.     if (hInstKernel32 != NULL)
  977.     {
  978.         pSetThreadExecutionState = (LPSETTHREADEXECUTIONSTATE)GetProcAddress(hInstKernel32, "SetThreadExecutionState");
  979.         if( pSetThreadExecutionState != NULL )
  980.         {
  981.             // Tell OS's that have power management to not 
  982.             // sleep, since this app will be using the 
  983.             // network connection and need very little user input
  984.             pSetThreadExecutionState( ES_SYSTEM_REQUIRED | ES_CONTINUOUS );
  985.         }
  986.  
  987.         FreeLibrary(hInstKernel32);
  988.     }
  989. }
  990.  
  991.  
  992.  
  993.  
  994.