2017-01-19 16:23:59 -05:00
# include " STDInclude.hpp "
namespace Components
{
WINDOW * Console : : OutputWindow ;
WINDOW * Console : : InputWindow ;
WINDOW * Console : : InfoWindow ;
int Console : : OutputTop = 0 ;
int Console : : OutBuffer = 0 ;
int Console : : LastRefresh = 0 ;
int Console : : Height = 25 ;
int Console : : Width = 80 ;
char Console : : LineBuffer [ 1024 ] = { 0 } ;
char Console : : LineBuffer2 [ 1024 ] = { 0 } ;
int Console : : LineBufferIndex = 0 ;
bool Console : : HasConsole = false ;
bool Console : : SkipShutdown = false ;
std : : thread Console : : ConsoleThread ;
Game : : SafeArea Console : : OriginalSafeArea ;
char * * Console : : GetAutoCompleteFileList ( const char * path , const char * extension , Game : : FsListBehavior_e behavior , int * numfiles , int allocTrackType )
{
2017-02-21 14:15:16 -05:00
if ( path = = reinterpret_cast < char * > ( 0xBAADF00D ) | | path = = reinterpret_cast < char * > ( 0xCDCDCDCD ) | | : : Utils : : Memory : : IsBadReadPtr ( path ) ) return nullptr ;
2017-01-19 16:23:59 -05:00
return Game : : FS_GetFileList ( path , extension , behavior , numfiles , allocTrackType ) ;
}
void Console : : ToggleConsole ( )
{
// possibly cls.keyCatchers?
Utils : : Hook : : Xor < DWORD > ( 0xB2C538 , 1 ) ;
// g_consoleField
2017-01-20 16:41:03 -05:00
Game : : Field_Clear ( reinterpret_cast < void * > ( 0xA1B6B0 ) ) ;
2017-01-19 16:23:59 -05:00
// show console output?
Utils : : Hook : : Set < BYTE > ( 0xA15F38 , 0 ) ;
}
void Console : : RefreshStatus ( )
{
std : : string mapname = Dvar : : Var ( " mapname " ) . get < const char * > ( ) ;
std : : string hostname = Colors : : Strip ( Dvar : : Var ( " sv_hostname " ) . get < const char * > ( ) ) ;
if ( Console : : HasConsole )
{
SetConsoleTitleA ( hostname . data ( ) ) ;
int clientCount = 0 ;
int maxclientCount = * Game : : svs_numclients ;
if ( maxclientCount )
{
for ( int i = 0 ; i < maxclientCount ; + + i )
{
if ( Game : : svs_clients [ i ] . state > = 3 )
{
+ + clientCount ;
}
}
}
else
{
2017-02-24 18:52:11 -05:00
maxclientCount = Dvar : : Var ( " party_maxplayers " ) . get < int > ( ) ;
//maxclientCount = Game::Party_GetMaxPlayers(*Game::partyIngame);
2017-01-19 16:23:59 -05:00
clientCount = Game : : PartyHost_CountMembers ( reinterpret_cast < Game : : PartyData_s * > ( 0x1081C00 ) ) ;
}
wclear ( Console : : InfoWindow ) ;
wprintw ( Console : : InfoWindow , " %s : %d/%d players : map %s " , hostname . data ( ) , clientCount , maxclientCount , ( mapname . size ( ) ? mapname . data ( ) : " none " ) ) ;
wnoutrefresh ( Console : : InfoWindow ) ;
}
2017-06-14 06:06:04 -04:00
else if ( IsWindow ( Console : : GetWindow ( ) ) ! = FALSE )
2017-01-19 16:23:59 -05:00
{
2017-02-10 03:50:08 -05:00
SetWindowTextA ( Console : : GetWindow ( ) , Utils : : String : : VA ( " IW4x( " VERSION " ) : %s " , hostname . data ( ) ) ) ;
2017-01-19 16:23:59 -05:00
}
}
void Console : : ShowPrompt ( )
{
wattron ( Console : : InputWindow , COLOR_PAIR ( 10 ) | A_BOLD ) ;
wprintw ( Console : : InputWindow , " %s> " , VERSION ) ;
}
void Console : : RefreshOutput ( )
{
2017-06-03 11:35:24 -04:00
prefresh ( Console : : OutputWindow , ( ( Console : : OutputTop > 0 ) ? ( Console : : OutputTop - 1 ) : 0 ) , 0 , 1 , 0 , Console : : Height - 2 , Console : : Width - 1 ) ;
2017-01-19 16:23:59 -05:00
}
void Console : : ScrollOutput ( int amount )
{
Console : : OutputTop + = amount ;
if ( Console : : OutputTop > OUTPUT_MAX_TOP )
{
Console : : OutputTop = OUTPUT_MAX_TOP ;
}
else if ( Console : : OutputTop < 0 )
{
Console : : OutputTop = 0 ;
}
// make it only scroll the top if there's more than HEIGHT lines
if ( Console : : OutBuffer > = 0 )
{
Console : : OutBuffer + = amount ;
if ( Console : : OutBuffer > = Console : : Height )
{
Console : : OutBuffer = - 1 ;
}
if ( Console : : OutputTop < Console : : Height )
{
Console : : OutputTop = 0 ;
}
}
}
const char * Console : : Input ( )
{
if ( ! Console : : HasConsole )
{
Console : : ShowPrompt ( ) ;
wrefresh ( Console : : InputWindow ) ;
Console : : HasConsole = true ;
}
int currentTime = static_cast < int > ( GetTickCount64 ( ) ) ; // Make our compiler happy
if ( ( currentTime - Console : : LastRefresh ) > 250 )
{
Console : : RefreshOutput ( ) ;
Console : : LastRefresh = currentTime ;
}
int c = wgetch ( Console : : InputWindow ) ;
if ( c = = ERR )
{
2017-01-20 16:41:03 -05:00
return nullptr ;
2017-01-19 16:23:59 -05:00
}
switch ( c )
{
case ' \r ' :
case 459 : // keypad enter
{
wattron ( Console : : OutputWindow , COLOR_PAIR ( 10 ) | A_BOLD ) ;
wprintw ( Console : : OutputWindow , " %s " , " ] " ) ;
if ( Console : : LineBufferIndex )
{
wprintw ( Console : : OutputWindow , " %s " , Console : : LineBuffer ) ;
}
wprintw ( Console : : OutputWindow , " %s " , " \n " ) ;
wattroff ( Console : : OutputWindow , A_BOLD ) ;
wclear ( Console : : InputWindow ) ;
Console : : ShowPrompt ( ) ;
wrefresh ( Console : : InputWindow ) ;
Console : : ScrollOutput ( 1 ) ;
Console : : RefreshOutput ( ) ;
if ( Console : : LineBufferIndex )
{
strcpy_s ( Console : : LineBuffer2 , Console : : LineBuffer ) ;
strcat_s ( Console : : LineBuffer , " \n " ) ;
Console : : LineBufferIndex = 0 ;
return Console : : LineBuffer ;
}
break ;
}
case ' c ' - ' a ' + 1 : // ctrl-c
case 27 :
{
Console : : LineBuffer [ 0 ] = ' \0 ' ;
Console : : LineBufferIndex = 0 ;
wclear ( Console : : InputWindow ) ;
Console : : ShowPrompt ( ) ;
wrefresh ( Console : : InputWindow ) ;
break ;
}
case 8 : // backspace
{
if ( Console : : LineBufferIndex > 0 )
{
Console : : LineBufferIndex - - ;
Console : : LineBuffer [ Console : : LineBufferIndex ] = ' \0 ' ;
wprintw ( Console : : InputWindow , " %c %c " , static_cast < char > ( c ) , static_cast < char > ( c ) ) ;
wrefresh ( Console : : InputWindow ) ;
}
break ;
}
case KEY_PPAGE :
{
Console : : ScrollOutput ( - 1 ) ;
Console : : RefreshOutput ( ) ;
break ;
}
case KEY_NPAGE :
{
Console : : ScrollOutput ( 1 ) ;
Console : : RefreshOutput ( ) ;
break ;
}
case KEY_UP :
{
wclear ( Console : : InputWindow ) ;
Console : : ShowPrompt ( ) ;
wprintw ( Console : : InputWindow , " %s " , Console : : LineBuffer2 ) ;
wrefresh ( Console : : InputWindow ) ;
strcpy_s ( Console : : LineBuffer , Console : : LineBuffer2 ) ;
Console : : LineBufferIndex = strlen ( Console : : LineBuffer ) ;
break ;
}
default :
if ( c < = 127 & & Console : : LineBufferIndex < 1022 )
{
// temporary workaround , find out what overwrites our index later on
//consoleLineBufferIndex = strlen(consoleLineBuffer);
Console : : LineBuffer [ Console : : LineBufferIndex + + ] = static_cast < char > ( c ) ;
Console : : LineBuffer [ Console : : LineBufferIndex ] = ' \0 ' ;
wprintw ( Console : : InputWindow , " %c " , static_cast < char > ( c ) ) ;
wrefresh ( Console : : InputWindow ) ;
}
break ;
}
2017-01-20 16:41:03 -05:00
return nullptr ;
2017-01-19 16:23:59 -05:00
}
void Console : : Destroy ( )
{
2017-07-14 05:36:37 -04:00
__try
2017-06-08 05:42:01 -04:00
{
2017-06-08 06:22:45 -04:00
delwin ( Console : : OutputWindow ) ;
delwin ( Console : : InputWindow ) ;
delwin ( Console : : InfoWindow ) ;
endwin ( ) ;
2017-06-08 05:42:01 -04:00
delscreen ( SP ) ;
}
2017-07-14 05:36:37 -04:00
__finally { }
2017-01-19 16:23:59 -05:00
Console : : OutputWindow = nullptr ;
Console : : InputWindow = nullptr ;
Console : : InfoWindow = nullptr ;
}
void Console : : Create ( )
{
Console : : OutputTop = 0 ;
Console : : OutBuffer = 0 ;
Console : : LastRefresh = 0 ;
Console : : LineBufferIndex = 0 ;
Console : : HasConsole = false ;
CONSOLE_SCREEN_BUFFER_INFO info ;
if ( GetConsoleScreenBufferInfo ( GetStdHandle ( STD_OUTPUT_HANDLE ) , & info ) )
{
Console : : Width = info . dwSize . X ;
Console : : Height = info . srWindow . Bottom - info . srWindow . Top + 1 ;
}
else
{
Console : : Height = 25 ;
Console : : Width = 80 ;
}
initscr ( ) ;
raw ( ) ;
noecho ( ) ;
Console : : OutputWindow = newpad ( Console : : Height - 1 , Console : : Width ) ;
Console : : InputWindow = newwin ( 1 , Console : : Width , Console : : Height - 1 , 0 ) ;
Console : : InfoWindow = newwin ( 1 , Console : : Width , 0 , 0 ) ;
scrollok ( Console : : OutputWindow , true ) ;
idlok ( Console : : OutputWindow , true ) ;
scrollok ( Console : : InputWindow , true ) ;
nodelay ( Console : : InputWindow , true ) ;
keypad ( Console : : InputWindow , true ) ;
if ( has_colors ( ) )
{
start_color ( ) ;
init_pair ( 1 , COLOR_BLACK , COLOR_WHITE ) ;
init_pair ( 2 , COLOR_WHITE , COLOR_BLACK ) ;
init_pair ( 3 , COLOR_RED , COLOR_BLACK ) ;
init_pair ( 4 , COLOR_GREEN , COLOR_BLACK ) ;
init_pair ( 5 , COLOR_YELLOW , COLOR_BLACK ) ;
init_pair ( 6 , COLOR_BLUE , COLOR_BLACK ) ;
init_pair ( 7 , COLOR_CYAN , COLOR_BLACK ) ;
init_pair ( 8 , COLOR_RED , COLOR_BLACK ) ;
init_pair ( 9 , COLOR_WHITE , COLOR_BLACK ) ;
init_pair ( 10 , COLOR_WHITE , COLOR_BLACK ) ;
}
wbkgd ( Console : : InfoWindow , COLOR_PAIR ( 1 ) ) ;
wrefresh ( Console : : InfoWindow ) ;
wrefresh ( Console : : InputWindow ) ;
Console : : RefreshOutput ( ) ;
}
void Console : : Error ( const char * format , . . . )
{
static char buffer [ 32768 ] ;
va_list va ;
va_start ( va , format ) ;
_vsnprintf_s ( buffer , sizeof ( buffer ) , format , va ) ;
va_end ( va ) ;
Game : : Com_Printf ( 0 , " ERROR: \n " ) ;
Game : : Com_Printf ( 0 , buffer ) ;
Console : : RefreshOutput ( ) ;
if ( IsDebuggerPresent ( ) )
{
while ( true )
{
std : : this_thread : : sleep_for ( 5 s ) ;
}
}
TerminateProcess ( GetCurrentProcess ( ) , 0xDEADDEAD ) ;
}
void Console : : Print ( const char * message )
{
if ( ! Console : : OutputWindow ) return ;
const char * p = message ;
while ( * p ! = ' \0 ' )
{
if ( * p = = ' ^ ' )
{
char color ;
+ + p ;
color = ( * p - ' 0 ' ) ;
if ( color < 9 & & color > 0 )
{
wattron ( Console : : OutputWindow , COLOR_PAIR ( color + 2 ) ) ;
+ + p ;
continue ;
}
}
waddch ( Console : : OutputWindow , * p ) ;
+ + p ;
}
wattron ( Console : : OutputWindow , COLOR_PAIR ( 9 ) ) ;
// int currentTime = static_cast<int>(GetTickCount64()); // Make our compiler happy
//
// if (!Console::HasConsole)
// {
// Console::RefreshOutput();
// }
// else if ((currentTime - Console::LastRefresh) > 100)
// {
// Console::RefreshOutput();
// Console::LastRefresh = currentTime;
// }
Console : : RefreshOutput ( ) ;
}
void Console : : ConsoleRunner ( )
{
Console : : SkipShutdown = false ;
Game : : Sys_ShowConsole ( ) ;
MSG message ;
2017-02-10 03:50:08 -05:00
while ( IsWindow ( Console : : GetWindow ( ) ) ! = FALSE & & GetMessageA ( & message , nullptr , 0 , 0 ) )
2017-01-19 16:23:59 -05:00
{
TranslateMessage ( & message ) ;
DispatchMessageA ( & message ) ;
}
if ( Console : : SkipShutdown ) return ;
if ( Game : : Sys_Milliseconds ( ) - Console : : LastRefresh > 100 & &
2017-01-20 16:41:03 -05:00
MessageBoxA ( nullptr , " The application is not responding anymore, do you want to force its termination? " , " Application is not responding " , MB_ICONEXCLAMATION | MB_YESNO ) = = IDYES )
2017-01-19 16:23:59 -05:00
{
// Force process termination
// if the main thread is not responding
OutputDebugStringA ( " Process termination forced, as the main thread is not responding! " ) ;
// We can not force the termination in this thread
// The destructor would be called in this thread
// and would try to join this thread, which is impossible
2017-02-12 11:15:41 -05:00
TerminateProcess ( GetCurrentProcess ( ) , 0xFFFFFFFF ) ;
2017-01-19 16:23:59 -05:00
}
else
{
// Send quit command to safely terminate the application
Command : : Execute ( " wait 200;quit \n " , false ) ;
}
}
void Console : : StdOutPrint ( const char * message )
{
printf ( " %s " , message ) ;
fflush ( stdout ) ;
}
void Console : : StdOutError ( const char * format , . . . )
{
char buffer [ 0x1000 ] = { 0 } ;
va_list ap ;
va_start ( ap , format ) ;
_vsnprintf_s ( buffer , sizeof ( buffer ) , format , ap ) ;
va_end ( ap ) ;
perror ( buffer ) ;
fflush ( stderr ) ;
ExitProcess ( 1 ) ;
}
__declspec ( naked ) void Console : : DrawSolidConsoleStub ( )
{
__asm
{
pushad
call Console : : StoreSafeArea
popad
// We need esi preserved here, so we have to backup 'all' registers when storing the safearea
call Game : : Con_DrawSolidConsole
2017-02-01 07:44:25 -05:00
pushad
2017-01-19 16:23:59 -05:00
call Console : : RestoreSafeArea
2017-02-01 07:44:25 -05:00
popad
2017-01-19 16:23:59 -05:00
retn
}
}
void Console : : StoreSafeArea ( )
{
// Backup the original safe area
Console : : OriginalSafeArea = * Game : : safeArea ;
// Apply new safe area and border
float border = 6.0f ;
Game : : safeArea - > top = border ;
Game : : safeArea - > left = border ;
Game : : safeArea - > bottom = static_cast < float > ( Renderer : : Height ( ) ) - border ;
Game : : safeArea - > right = static_cast < float > ( Renderer : : Width ( ) ) - border ;
Game : : safeArea - > textHeight = static_cast < int > ( ( Game : : safeArea - > bottom - Game : : safeArea - > top - ( 2 * Game : : safeArea - > fontHeight ) - 24.0 ) / Game : : safeArea - > fontHeight ) ;
Game : : safeArea - > textWidth = static_cast < int > ( Game : : safeArea - > right - Game : : safeArea - > left - 10.0f - 18.0 ) ;
}
void Console : : RestoreSafeArea ( )
{
// Restore the initial safe area
* Game : : safeArea = Console : : OriginalSafeArea ;
}
void Console : : SetSkipShutdown ( )
{
Console : : SkipShutdown = true ;
}
void Console : : FreeNativeConsole ( )
{
2017-07-03 09:40:32 -04:00
if ( ! Monitor : : IsEnabled ( ) & & ! Flags : : HasFlag ( " stdout " ) & & ( ! Dedicated : : IsEnabled ( ) | | Flags : : HasFlag ( " console " ) ) & & ! Loader : : IsPerformingUnitTests ( ) )
2017-01-19 16:23:59 -05:00
{
FreeConsole ( ) ;
}
}
2017-02-10 03:50:08 -05:00
HWND Console : : GetWindow ( )
{
return * reinterpret_cast < HWND * > ( 0x64A3288 ) ;
}
2017-05-27 11:17:12 -04:00
void Console : : ShowAsyncConsole ( )
{
Console : : ConsoleThread = std : : thread ( Console : : ConsoleRunner ) ;
}
2017-01-19 16:23:59 -05:00
Game : : dvar_t * Console : : RegisterConColor ( const char * name , float r , float g , float b , float a , float min , float max , int flags , const char * description )
{
static struct
{
const char * name ;
float color [ 4 ] ;
} patchedColors [ ] =
{
{ " con_inputBoxColor " , { 0.20f , 0.20f , 0.20f , 1.00f } } ,
{ " con_inputHintBoxColor " , { 0.30f , 0.30f , 0.30f , 1.00f } } ,
{ " con_outputBarColor " , { 0.50f , 0.50f , 0.50f , 0.60f } } ,
{ " con_outputSliderColor " , { 0.70f , 1.00f , 0.00f , 1.00f } } ,
{ " con_outputWindowColor " , { 0.25f , 0.25f , 0.25f , 0.85f } } ,
} ;
2017-01-27 08:43:52 -05:00
for ( int i = 0 ; i < ARRAYSIZE ( patchedColors ) ; + + i )
2017-01-19 16:23:59 -05:00
{
if ( std : : string ( name ) = = patchedColors [ i ] . name )
{
r = patchedColors [ i ] . color [ 0 ] ;
g = patchedColors [ i ] . color [ 1 ] ;
b = patchedColors [ i ] . color [ 2 ] ;
a = patchedColors [ i ] . color [ 3 ] ;
break ;
}
}
return reinterpret_cast < Game : : Dvar_RegisterVec4_t > ( 0x471500 ) ( name , r , g , b , a , min , max , flags , description ) ;
}
Console : : Console ( )
{
// Console '%s: %s> ' string
Utils : : Hook : : Set < char * > ( 0x5A44B4 , " IW4x: " VERSION " > " ) ;
// Patch console color
static float consoleColor [ ] = { 0.70f , 1.00f , 0.00f , 1.00f } ;
Utils : : Hook : : Set < float * > ( 0x5A451A , consoleColor ) ;
Utils : : Hook : : Set < float * > ( 0x5A4400 , consoleColor ) ;
// Internal console
Utils : : Hook ( 0x4F690C , Console : : ToggleConsole , HOOK_CALL ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x4F65A5 , Console : : ToggleConsole , HOOK_JUMP ) . install ( ) - > quick ( ) ;
// Patch safearea for ingame-console
Utils : : Hook ( 0x5A50EF , Console : : DrawSolidConsoleStub , HOOK_CALL ) . install ( ) - > quick ( ) ;
// Check for bad food ;)
Utils : : Hook ( 0x4CB9F4 , Console : : GetAutoCompleteFileList , HOOK_CALL ) . install ( ) - > quick ( ) ;
// Patch console dvars
Utils : : Hook ( 0x4829AB , Console : : RegisterConColor , HOOK_CALL ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x4829EE , Console : : RegisterConColor , HOOK_CALL ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x482A31 , Console : : RegisterConColor , HOOK_CALL ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x482A7A , Console : : RegisterConColor , HOOK_CALL ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x482AC3 , Console : : RegisterConColor , HOOK_CALL ) . install ( ) - > quick ( ) ;
// Modify console style
Utils : : Hook : : Set < BYTE > ( 0x428A8E , 0 ) ; // Adjust logo Y pos
Utils : : Hook : : Set < BYTE > ( 0x428A90 , 0 ) ; // Adjust logo X pos
Utils : : Hook : : Set < BYTE > ( 0x428AF2 , 67 ) ; // Adjust output Y pos
Utils : : Hook : : Set < DWORD > ( 0x428AC5 , 397 ) ; // Adjust input Y pos
Utils : : Hook : : Set < DWORD > ( 0x428951 , 609 ) ; // Reduce window width
Utils : : Hook : : Set < DWORD > ( 0x42895D , 423 ) ; // Reduce window height
Utils : : Hook : : Set < DWORD > ( 0x428AC0 , 597 ) ; // Reduce input width
Utils : : Hook : : Set < DWORD > ( 0x428AED , 596 ) ; // Reduce output width
// Don't resize the console
Utils : : Hook ( 0x64DC6B , 0x64DCC2 , HOOK_JUMP ) . install ( ) - > quick ( ) ;
if ( Dedicated : : IsEnabled ( ) & & ! ZoneBuilder : : IsEnabled ( ) )
{
2017-05-31 10:09:41 -04:00
Scheduler : : OnFrame ( Console : : RefreshStatus ) ;
2017-01-19 16:23:59 -05:00
}
// Code below is not necessary when performing unit tests!
2017-07-03 09:40:32 -04:00
if ( Loader : : IsPerformingUnitTests ( ) ) return ;
2017-01-19 16:23:59 -05:00
// External console
2017-02-25 09:32:15 -05:00
if ( Flags : : HasFlag ( " stdout " ) | | Monitor : : IsEnabled ( ) )
2017-01-19 16:23:59 -05:00
{
2017-02-25 09:32:15 -05:00
# ifndef DEBUG
if ( ! Monitor : : IsEnabled ( ) )
# endif
{
Utils : : Hook ( 0x4B2080 , Console : : StdOutPrint , HOOK_JUMP ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x43D570 , Console : : StdOutError , HOOK_JUMP ) . install ( ) - > quick ( ) ;
}
2017-01-19 16:23:59 -05:00
}
else if ( Flags : : HasFlag ( " console " ) | | ZoneBuilder : : IsEnabled ( ) ) // ZoneBuilder uses the game's console, until the native one is adapted.
{
Utils : : Hook : : Nop ( 0x60BB58 , 11 ) ;
// Redirect input (]command)
Utils : : Hook ( 0x47025A , 0x4F5770 , HOOK_CALL ) . install ( ) - > quick ( ) ;
2017-06-14 06:06:04 -04:00
Utils : : Hook ( 0x60BB68 , [ ] ( )
2017-01-19 16:23:59 -05:00
{
2017-05-27 11:17:12 -04:00
Console : : ShowAsyncConsole ( ) ;
2017-01-19 16:23:59 -05:00
} , HOOK_CALL ) . install ( ) - > quick ( ) ;
2017-01-25 09:00:05 -05:00
Utils : : Hook ( 0x4D69A2 , [ ] ( )
{
Console : : SetSkipShutdown ( ) ;
// Sys_DestroyConsole
Utils : : Hook : : Call < void ( ) > ( 0x4528A0 ) ( ) ;
if ( Console : : ConsoleThread . joinable ( ) )
{
Console : : ConsoleThread . join ( ) ;
}
} , HOOK_CALL ) . install ( ) - > quick ( ) ;
2017-06-14 06:06:04 -04:00
Scheduler : : OnFrame ( [ ] ( )
2017-01-19 16:23:59 -05:00
{
Console : : LastRefresh = Game : : Sys_Milliseconds ( ) ;
} ) ;
}
else if ( Dedicated : : IsEnabled ( ) /* || ZoneBuilder::IsEnabled()*/ )
{
2017-06-04 04:35:45 -04:00
DWORD type = GetFileType ( GetStdHandle ( STD_INPUT_HANDLE ) ) ;
if ( type ! = FILE_TYPE_CHAR )
{
MessageBoxA ( nullptr , " Console not supported, please use '-stdout' or '-console' flag! " , " ERRROR " , MB_ICONERROR ) ;
TerminateProcess ( GetCurrentProcess ( ) , 1 ) ;
}
2017-01-19 16:23:59 -05:00
Utils : : Hook : : Nop ( 0x60BB58 , 11 ) ;
Utils : : Hook ( 0x4305E0 , Console : : Create , HOOK_JUMP ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x4528A0 , Console : : Destroy , HOOK_JUMP ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x4B2080 , Console : : Print , HOOK_JUMP ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x43D570 , Console : : Error , HOOK_JUMP ) . install ( ) - > quick ( ) ;
Utils : : Hook ( 0x4859A5 , Console : : Input , HOOK_CALL ) . install ( ) - > quick ( ) ;
}
2017-07-03 09:40:32 -04:00
else if ( ! Loader : : IsPerformingUnitTests ( ) )
2017-01-19 16:23:59 -05:00
{
FreeConsole ( ) ;
}
}
Console : : ~ Console ( )
{
2017-01-25 09:00:05 -05:00
Console : : SetSkipShutdown ( ) ;
2017-01-19 16:23:59 -05:00
if ( Console : : ConsoleThread . joinable ( ) )
{
Console : : ConsoleThread . join ( ) ;
}
}
}