2010-11-20 10:37:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
2010-08-07 18:22:25 +00:00
# include <new>
2011-07-05 19:54:10 +00:00
# include <base/math.h>
2010-05-29 07:25:38 +00:00
# include <base/system.h>
2011-07-05 19:54:10 +00:00
2010-05-29 07:25:38 +00:00
# include <engine/storage.h>
2011-07-05 19:54:10 +00:00
# include <engine/shared/protocol.h>
2010-05-29 07:25:38 +00:00
# include "config.h"
2011-07-05 19:54:10 +00:00
# include "console.h"
2010-05-29 07:25:38 +00:00
# include "linereader.h"
2011-12-30 18:12:31 +00:00
// todo: rework this
2010-05-29 07:25:38 +00:00
const char * CConsole : : CResult : : GetString ( unsigned Index )
{
2012-08-16 22:03:53 +00:00
if ( Index > = m_NumArgs )
2010-05-29 07:25:38 +00:00
return " " ;
return m_apArgs [ Index ] ;
}
int CConsole : : CResult : : GetInteger ( unsigned Index )
{
2012-08-16 22:03:53 +00:00
if ( Index > = m_NumArgs )
2010-05-29 07:25:38 +00:00
return 0 ;
return str_toint ( m_apArgs [ Index ] ) ;
}
float CConsole : : CResult : : GetFloat ( unsigned Index )
{
2012-08-16 22:03:53 +00:00
if ( Index > = m_NumArgs )
2010-05-29 07:25:38 +00:00
return 0.0f ;
return str_tofloat ( m_apArgs [ Index ] ) ;
}
2011-07-14 20:07:21 +00:00
const IConsole : : CCommandInfo * CConsole : : CCommand : : NextCommandInfo ( int AccessLevel , int FlagMask ) const
{
const CCommand * pInfo = m_pNext ;
while ( pInfo )
{
if ( pInfo - > m_Flags & FlagMask & & pInfo - > m_AccessLevel > = AccessLevel )
break ;
pInfo = pInfo - > m_pNext ;
}
return pInfo ;
}
const IConsole : : CCommandInfo * CConsole : : FirstCommandInfo ( int AccessLevel , int FlagMask ) const
{
for ( const CCommand * pCommand = m_pFirstCommand ; pCommand ; pCommand = pCommand - > m_pNext )
{
if ( pCommand - > m_Flags & FlagMask & & pCommand - > GetAccessLevel ( ) > = AccessLevel )
return pCommand ;
}
return 0 ;
2011-04-12 20:18:15 +00:00
}
2010-05-29 07:25:38 +00:00
// the maximum number of tokens occurs in a string of length CONSOLE_MAX_STR_LENGTH with tokens size 1 separated by single spaces
int CConsole : : ParseStart ( CResult * pResult , const char * pString , int Length )
{
char * pStr ;
int Len = sizeof ( pResult - > m_aStringStorage ) ;
if ( Length < Len )
Len = Length ;
2011-04-13 18:37:12 +00:00
2012-08-17 16:32:56 +00:00
str_copy ( pResult - > m_aStringStorage , pString , Len ) ;
2010-05-29 07:25:38 +00:00
pStr = pResult - > m_aStringStorage ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
// get command
2010-08-12 13:44:11 +00:00
pStr = str_skip_whitespaces ( pStr ) ;
2010-05-29 07:25:38 +00:00
pResult - > m_pCommand = pStr ;
2010-10-25 16:41:15 +00:00
pStr = str_skip_to_whitespace ( pStr ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
if ( * pStr )
{
pStr [ 0 ] = 0 ;
pStr + + ;
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
pResult - > m_pArgsStart = pStr ;
return 0 ;
}
int CConsole : : ParseArgs ( CResult * pResult , const char * pFormat )
{
2015-12-28 15:14:52 +00:00
char Command = * pFormat ;
2010-05-29 07:25:38 +00:00
char * pStr ;
int Optional = 0 ;
int Error = 0 ;
2010-11-07 15:29:55 +00:00
2011-09-25 16:04:29 +00:00
pResult - > ResetVictim ( ) ;
2010-05-29 07:25:38 +00:00
pStr = pResult - > m_pArgsStart ;
2011-04-13 18:37:12 +00:00
while ( 1 )
2010-05-29 07:25:38 +00:00
{
if ( ! Command )
break ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
if ( Command = = ' ? ' )
Optional = 1 ;
else
{
2010-08-12 13:44:11 +00:00
pStr = str_skip_whitespaces ( pStr ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
if ( ! ( * pStr ) ) // error, non optional command needs value
{
if ( ! Optional )
2011-09-25 16:04:29 +00:00
{
2010-05-29 07:25:38 +00:00
Error = 1 ;
2011-09-25 16:04:29 +00:00
break ;
}
2015-12-28 15:14:52 +00:00
while ( Command )
2011-09-25 16:04:29 +00:00
{
2015-12-28 15:14:52 +00:00
if ( Command = = ' v ' )
2011-09-25 16:04:29 +00:00
{
pResult - > SetVictim ( CResult : : VICTIM_ME ) ;
break ;
}
2015-12-28 15:14:52 +00:00
Command = NextParam ( pFormat ) ;
2011-09-25 16:04:29 +00:00
}
2010-05-29 07:25:38 +00:00
break ;
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
// add token
if ( * pStr = = ' " ' )
{
char * pDst ;
pStr + + ;
pResult - > AddArgument ( pStr ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
pDst = pStr ; // we might have to process escape data
while ( 1 )
{
if ( pStr [ 0 ] = = ' " ' )
break ;
else if ( pStr [ 0 ] = = ' \\ ' )
{
if ( pStr [ 1 ] = = ' \\ ' )
pStr + + ; // skip due to escape
else if ( pStr [ 1 ] = = ' " ' )
pStr + + ; // skip due to escape
}
else if ( pStr [ 0 ] = = 0 )
return 1 ; // return error
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
* pDst = * pStr ;
pDst + + ;
pStr + + ;
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
// write null termination
* pDst = 0 ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
pStr + + ;
}
else
{
2011-09-25 16:04:29 +00:00
char * pVictim = 0 ;
if ( Command ! = ' v ' )
2015-12-28 15:14:52 +00:00
pResult - > AddArgument ( pStr ) ;
2011-09-25 16:04:29 +00:00
else
pVictim = pStr ;
2010-11-15 17:58:44 +00:00
2010-05-29 07:25:38 +00:00
if ( Command = = ' r ' ) // rest of the string
break ;
2011-09-25 16:04:29 +00:00
else if ( Command = = ' v ' ) // validate victim
pStr = str_skip_to_whitespace ( pStr ) ;
2010-05-29 07:25:38 +00:00
else if ( Command = = ' i ' ) // validate int
2010-10-25 16:41:15 +00:00
pStr = str_skip_to_whitespace ( pStr ) ;
2010-05-29 07:25:38 +00:00
else if ( Command = = ' f ' ) // validate float
2010-10-25 16:41:15 +00:00
pStr = str_skip_to_whitespace ( pStr ) ;
2010-05-29 07:25:38 +00:00
else if ( Command = = ' s ' ) // validate string
2010-10-25 16:41:15 +00:00
pStr = str_skip_to_whitespace ( pStr ) ;
2010-05-29 07:25:38 +00:00
if ( pStr [ 0 ] ! = 0 ) // check for end of string
{
pStr [ 0 ] = 0 ;
pStr + + ;
}
2011-09-25 16:04:29 +00:00
if ( pVictim )
pResult - > SetVictim ( pVictim ) ;
2010-05-29 07:25:38 +00:00
}
}
2015-12-28 15:14:52 +00:00
// fetch next command
Command = NextParam ( pFormat ) ;
2010-05-29 07:25:38 +00:00
}
return Error ;
}
2015-12-28 15:14:52 +00:00
char CConsole : : NextParam ( const char * & pFormat )
{
if ( * pFormat )
{
pFormat + + ;
if ( * pFormat = = ' [ ' )
{
// skip bracket contents
2015-12-28 23:45:51 +00:00
for ( ; * pFormat ! = ' ] ' ; pFormat + + )
{
if ( ! * pFormat )
return * pFormat ;
}
2015-12-28 15:14:52 +00:00
// skip ']'
pFormat + + ;
// skip space if there is one
if ( * pFormat = = ' ' )
pFormat + + ;
}
}
return * pFormat ;
}
2011-07-30 11:40:01 +00:00
int CConsole : : RegisterPrintCallback ( int OutputLevel , FPrintCallback pfnPrintCallback , void * pUserData )
2010-05-29 07:25:38 +00:00
{
2011-07-30 11:40:01 +00:00
if ( m_NumPrintCB = = MAX_PRINT_CB )
return - 1 ;
m_aPrintCB [ m_NumPrintCB ] . m_OutputLevel = clamp ( OutputLevel , ( int ) ( OUTPUT_LEVEL_STANDARD ) , ( int ) ( OUTPUT_LEVEL_DEBUG ) ) ;
m_aPrintCB [ m_NumPrintCB ] . m_pfnPrintCallback = pfnPrintCallback ;
m_aPrintCB [ m_NumPrintCB ] . m_pPrintCallbackUserdata = pUserData ;
return m_NumPrintCB + + ;
}
void CConsole : : SetPrintOutputLevel ( int Index , int OutputLevel )
{
if ( Index > = 0 & & Index < MAX_PRINT_CB )
m_aPrintCB [ Index ] . m_OutputLevel = clamp ( OutputLevel , ( int ) ( OUTPUT_LEVEL_STANDARD ) , ( int ) ( OUTPUT_LEVEL_DEBUG ) ) ;
2010-05-29 07:25:38 +00:00
}
2014-12-20 12:37:11 +00:00
void CConsole : : Print ( int Level , const char * pFrom , const char * pStr , bool Highlighted )
2010-05-29 07:25:38 +00:00
{
2010-08-17 22:06:00 +00:00
dbg_msg ( pFrom , " %s " , pStr ) ;
2011-07-30 11:40:01 +00:00
for ( int i = 0 ; i < m_NumPrintCB ; + + i )
2010-08-17 22:06:00 +00:00
{
2011-07-30 11:40:01 +00:00
if ( Level < = m_aPrintCB [ i ] . m_OutputLevel & & m_aPrintCB [ i ] . m_pfnPrintCallback )
{
char aBuf [ 1024 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " [%s]: %s " , pFrom , pStr ) ;
2014-12-20 12:37:11 +00:00
m_aPrintCB [ i ] . m_pfnPrintCallback ( aBuf , m_aPrintCB [ i ] . m_pPrintCallbackUserdata , Highlighted ) ;
2011-07-30 11:40:01 +00:00
}
2010-10-10 22:40:07 +00:00
}
}
2010-10-25 16:30:35 +00:00
bool CConsole : : LineIsValid ( const char * pStr )
{
if ( ! pStr | | * pStr = = 0 )
return false ;
2011-04-13 18:37:12 +00:00
2010-10-25 16:30:35 +00:00
do
{
CResult Result ;
const char * pEnd = pStr ;
const char * pNextPart = 0 ;
int InString = 0 ;
2011-04-13 18:37:12 +00:00
2010-10-25 16:30:35 +00:00
while ( * pEnd )
{
if ( * pEnd = = ' " ' )
InString ^ = 1 ;
else if ( * pEnd = = ' \\ ' ) // escape sequences
{
if ( pEnd [ 1 ] = = ' " ' )
pEnd + + ;
}
else if ( ! InString )
{
2011-04-13 18:37:12 +00:00
if ( * pEnd = = ' ; ' ) // command separator
2010-10-25 16:30:35 +00:00
{
pNextPart = pEnd + 1 ;
break ;
}
2011-04-13 18:37:12 +00:00
else if ( * pEnd = = ' # ' ) // comment, no need to do anything more
2010-10-25 16:30:35 +00:00
break ;
}
2011-04-13 18:37:12 +00:00
2010-10-25 16:30:35 +00:00
pEnd + + ;
}
2011-04-13 18:37:12 +00:00
2010-10-25 16:30:35 +00:00
if ( ParseStart ( & Result , pStr , ( pEnd - pStr ) + 1 ) ! = 0 )
return false ;
CCommand * pCommand = FindCommand ( Result . m_pCommand , m_FlagMask ) ;
if ( ! pCommand | | ParseArgs ( & Result , pCommand - > m_pParams ) )
return false ;
2011-04-13 18:37:12 +00:00
2010-10-25 16:30:35 +00:00
pStr = pNextPart ;
}
while ( pStr & & * pStr ) ;
return true ;
}
2017-01-03 13:01:51 +00:00
void CConsole : : ExecuteLineStroked ( int Stroke , const char * pStr , int ClientID , bool InterpretSemicolons )
2011-04-13 18:37:12 +00:00
{
2017-01-03 13:01:51 +00:00
static const char s_aMulticommandPrefix [ ] = " mc; " ;
static const int s_PrefixLength = str_length ( s_aMulticommandPrefix ) ;
if ( str_length ( pStr ) > = s_PrefixLength
& & str_comp_num ( pStr , s_aMulticommandPrefix , s_PrefixLength ) = = 0 )
{
InterpretSemicolons = true ;
pStr + = s_PrefixLength ;
}
2010-05-29 07:25:38 +00:00
while ( pStr & & * pStr )
{
2011-01-07 18:33:29 +00:00
CResult Result ;
2011-08-26 18:03:30 +00:00
Result . m_ClientID = ClientID ;
2010-05-29 07:25:38 +00:00
const char * pEnd = pStr ;
const char * pNextPart = 0 ;
int InString = 0 ;
2011-04-12 20:18:15 +00:00
2010-05-29 07:25:38 +00:00
while ( * pEnd )
{
if ( * pEnd = = ' " ' )
InString ^ = 1 ;
else if ( * pEnd = = ' \\ ' ) // escape sequences
{
if ( pEnd [ 1 ] = = ' " ' )
pEnd + + ;
}
2017-01-03 13:01:51 +00:00
else if ( ! InString & & InterpretSemicolons )
2010-05-29 07:25:38 +00:00
{
2011-04-13 18:37:12 +00:00
if ( * pEnd = = ' ; ' ) // command separator
2010-05-29 07:25:38 +00:00
{
pNextPart = pEnd + 1 ;
break ;
}
2011-04-13 18:37:12 +00:00
else if ( * pEnd = = ' # ' ) // comment, no need to do anything more
2010-05-29 07:25:38 +00:00
break ;
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
pEnd + + ;
}
2011-04-13 18:37:12 +00:00
2011-01-07 18:33:29 +00:00
if ( ParseStart ( & Result , pStr , ( pEnd - pStr ) + 1 ) ! = 0 )
2011-08-31 00:48:58 +00:00
return ;
2010-05-29 07:25:38 +00:00
2011-07-05 19:54:10 +00:00
if ( ! * Result . m_pCommand )
2011-08-31 00:48:58 +00:00
return ;
2011-05-20 00:43:31 +00:00
2011-01-07 18:33:29 +00:00
CCommand * pCommand = FindCommand ( Result . m_pCommand , m_FlagMask ) ;
2010-05-29 07:25:38 +00:00
if ( pCommand )
{
2015-07-15 12:02:21 +00:00
if ( ClientID = = IConsole : : CLIENT_ID_GAME
& & ! ( pCommand - > m_Flags & CFGFLAG_GAME ) )
{
if ( Stroke )
{
char aBuf [ 96 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " Command '%s' cannot be executed from a map. " , Result . m_pCommand ) ;
Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
}
}
else if ( ClientID = = IConsole : : CLIENT_ID_NO_GAME
& & pCommand - > m_Flags & CFGFLAG_GAME )
{
if ( Stroke )
{
char aBuf [ 96 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " Command '%s' cannot be executed from a non-map config file. " , Result . m_pCommand ) ;
Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
str_format ( aBuf , sizeof ( aBuf ) , " Hint: Put the command in '%s.cfg' instead of '%s.map.cfg' " , g_Config . m_SvMap , g_Config . m_SvMap ) ;
Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
}
}
else if ( pCommand - > GetAccessLevel ( ) > = m_AccessLevel )
2010-05-29 07:25:38 +00:00
{
2011-07-05 19:54:10 +00:00
int IsStrokeCommand = 0 ;
if ( Result . m_pCommand [ 0 ] = = ' + ' )
2010-05-29 07:25:38 +00:00
{
2011-07-05 19:54:10 +00:00
// insert the stroke direction token
Result . AddArgument ( m_paStrokeStr [ Stroke ] ) ;
IsStrokeCommand = 1 ;
2010-05-29 07:25:38 +00:00
}
2011-07-05 19:54:10 +00:00
if ( Stroke | | IsStrokeCommand )
2010-09-06 03:22:00 +00:00
{
2011-07-05 19:54:10 +00:00
if ( ParseArgs ( & Result , pCommand - > m_pParams ) )
{
char aBuf [ 256 ] ;
2015-12-28 15:14:52 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Invalid arguments... Usage: %s %s " , pCommand - > m_pName , pCommand - > m_pParams ) ;
2014-09-06 21:22:35 +00:00
Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2011-07-05 19:54:10 +00:00
}
else if ( m_StoreCommands & & pCommand - > m_Flags & CFGFLAG_STORE )
{
m_ExecutionQueue . AddEntry ( ) ;
m_ExecutionQueue . m_pLast - > m_pfnCommandCallback = pCommand - > m_pfnCallback ;
m_ExecutionQueue . m_pLast - > m_pCommandUserData = pCommand - > m_pUserData ;
m_ExecutionQueue . m_pLast - > m_Result = Result ;
}
else
2011-08-26 21:24:46 +00:00
{
2011-09-25 16:04:29 +00:00
if ( Result . GetVictim ( ) = = CResult : : VICTIM_ME )
Result . SetVictim ( ClientID ) ;
2013-07-22 22:15:50 +00:00
if ( pCommand - > m_Flags & CMDFLAG_TEST & & ! g_Config . m_SvTestingCommands )
2011-08-31 00:48:58 +00:00
return ;
2011-09-25 16:04:29 +00:00
if ( Result . HasVictim ( ) )
{
if ( Result . GetVictim ( ) = = CResult : : VICTIM_ALL )
{
for ( int i = 0 ; i < MAX_CLIENTS ; i + + )
{
Result . SetVictim ( i ) ;
2011-07-05 19:54:10 +00:00
pCommand - > m_pfnCallback ( & Result , pCommand - > m_pUserData ) ;
2011-09-25 16:04:29 +00:00
}
}
else
2011-12-31 22:00:00 +00:00
pCommand - > m_pfnCallback ( & Result , pCommand - > m_pUserData ) ;
2011-09-25 16:04:29 +00:00
}
else
2011-12-31 22:00:00 +00:00
pCommand - > m_pfnCallback ( & Result , pCommand - > m_pUserData ) ;
2011-09-25 16:04:29 +00:00
2011-08-31 00:48:58 +00:00
if ( pCommand - > m_Flags & CMDFLAG_TEST )
2011-08-26 21:24:46 +00:00
m_Cheated = true ;
}
2010-09-06 03:22:00 +00:00
}
2011-07-05 19:54:10 +00:00
}
else if ( Stroke )
{
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " Access for command %s denied. " , Result . m_pCommand ) ;
2014-09-06 21:22:35 +00:00
Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2010-05-29 07:25:38 +00:00
}
}
2010-06-18 18:32:52 +00:00
else if ( Stroke )
2010-05-29 07:25:38 +00:00
{
char aBuf [ 256 ] ;
2011-01-07 18:33:29 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " No such command: %s. " , Result . m_pCommand ) ;
2014-09-06 21:22:35 +00:00
Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2010-05-29 07:25:38 +00:00
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
pStr = pNextPart ;
}
}
2011-07-14 20:07:21 +00:00
void CConsole : : PossibleCommands ( const char * pStr , int FlagMask , bool Temp , FPossibleCallback pfnCallback , void * pUser )
2010-05-29 07:25:38 +00:00
{
2011-07-05 19:54:10 +00:00
for ( CCommand * pCommand = m_pFirstCommand ; pCommand ; pCommand = pCommand - > m_pNext )
2010-05-29 07:25:38 +00:00
{
2011-07-14 20:07:21 +00:00
if ( pCommand - > m_Flags & FlagMask & & pCommand - > m_Temp = = Temp )
2010-05-29 07:25:38 +00:00
{
if ( str_find_nocase ( pCommand - > m_pName , pStr ) )
pfnCallback ( pCommand - > m_pName , pUser ) ;
}
2011-04-13 18:37:12 +00:00
}
2010-05-29 07:25:38 +00:00
}
2010-06-18 18:32:52 +00:00
CConsole : : CCommand * CConsole : : FindCommand ( const char * pName , int FlagMask )
2010-05-29 07:25:38 +00:00
{
2011-07-05 19:54:10 +00:00
for ( CCommand * pCommand = m_pFirstCommand ; pCommand ; pCommand = pCommand - > m_pNext )
2010-05-29 07:25:38 +00:00
{
2010-06-18 18:32:52 +00:00
if ( pCommand - > m_Flags & FlagMask )
{
if ( str_comp_nocase ( pCommand - > m_pName , pName ) = = 0 )
return pCommand ;
}
2011-04-13 18:37:12 +00:00
}
2010-05-29 07:25:38 +00:00
return 0x0 ;
}
2017-01-03 13:01:51 +00:00
void CConsole : : ExecuteLine ( const char * pStr , int ClientID , bool InterpretSemicolons )
2011-04-12 20:18:15 +00:00
{
2017-01-03 13:01:51 +00:00
CConsole : : ExecuteLineStroked ( 1 , pStr , ClientID , InterpretSemicolons ) ; // press it
CConsole : : ExecuteLineStroked ( 0 , pStr , ClientID , InterpretSemicolons ) ; // then release it
2011-04-12 20:18:15 +00:00
}
2017-01-03 13:01:51 +00:00
void CConsole : : ExecuteLineFlag ( const char * pStr , int FlagMask , int ClientID , bool InterpretSemicolons )
2011-12-30 18:12:31 +00:00
{
int Temp = m_FlagMask ;
m_FlagMask = FlagMask ;
2017-01-03 13:01:51 +00:00
ExecuteLine ( pStr , ClientID , InterpretSemicolons ) ;
2011-12-30 18:12:31 +00:00
m_FlagMask = Temp ;
}
2010-05-29 07:25:38 +00:00
2016-05-02 19:35:32 +00:00
void CConsole : : ExecuteFile ( const char * pFilename , int ClientID , bool LogFailure )
2010-05-29 07:25:38 +00:00
{
// make sure that this isn't being executed already
for ( CExecFile * pCur = m_pFirstExec ; pCur ; pCur = pCur - > m_pPrev )
if ( str_comp ( pFilename , pCur - > m_pFilename ) = = 0 )
return ;
if ( ! m_pStorage )
m_pStorage = Kernel ( ) - > RequestInterface < IStorage > ( ) ;
if ( ! m_pStorage )
return ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
// push this one to the stack
CExecFile ThisFile ;
CExecFile * pPrev = m_pFirstExec ;
ThisFile . m_pFilename = pFilename ;
ThisFile . m_pPrev = m_pFirstExec ;
m_pFirstExec = & ThisFile ;
// exec the file
2010-10-06 21:07:35 +00:00
IOHANDLE File = m_pStorage - > OpenFile ( pFilename , IOFLAG_READ , IStorage : : TYPE_ALL ) ;
2011-04-13 18:37:12 +00:00
2015-07-14 20:08:29 +00:00
char aBuf [ 128 ] ;
2010-05-29 07:25:38 +00:00
if ( File )
{
char * pLine ;
CLineReader lr ;
2011-04-13 18:37:12 +00:00
2010-08-17 22:06:00 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " executing '%s' " , pFilename ) ;
2011-08-13 00:11:06 +00:00
Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2010-05-29 07:25:38 +00:00
lr . Init ( File ) ;
while ( ( pLine = lr . Get ( ) ) )
2011-08-26 18:03:30 +00:00
ExecuteLine ( pLine , ClientID ) ;
2010-05-29 07:25:38 +00:00
io_close ( File ) ;
}
2016-05-02 19:35:32 +00:00
else if ( LogFailure )
2010-08-17 22:06:00 +00:00
{
str_format ( aBuf , sizeof ( aBuf ) , " failed to open '%s' " , pFilename ) ;
2011-08-13 00:11:06 +00:00
Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2010-08-17 22:06:00 +00:00
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
m_pFirstExec = pPrev ;
}
2011-08-13 00:11:06 +00:00
void CConsole : : Con_Echo ( IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
2014-09-06 21:22:35 +00:00
( ( CConsole * ) pUserData ) - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " console " , pResult - > GetString ( 0 ) ) ;
2010-05-29 07:25:38 +00:00
}
2011-08-13 00:11:06 +00:00
void CConsole : : Con_Exec ( IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
2016-05-02 19:35:32 +00:00
( ( CConsole * ) pUserData ) - > ExecuteFile ( pResult - > GetString ( 0 ) , - 1 , true ) ;
2010-05-29 07:25:38 +00:00
}
2015-10-23 00:33:10 +00:00
void CConsole : : ConCommandAccess ( IResult * pResult , void * pUser )
2011-07-05 19:54:10 +00:00
{
CConsole * pConsole = static_cast < CConsole * > ( pUser ) ;
char aBuf [ 128 ] ;
CCommand * pCommand = pConsole - > FindCommand ( pResult - > GetString ( 0 ) , CFGFLAG_SERVER ) ;
if ( pCommand )
{
if ( pResult - > NumArguments ( ) = = 2 )
{
2011-07-14 20:07:21 +00:00
pCommand - > SetAccessLevel ( pResult - > GetInteger ( 1 ) ) ;
str_format ( aBuf , sizeof ( aBuf ) , " moderator access for '%s' is now %s " , pResult - > GetString ( 0 ) , pCommand - > GetAccessLevel ( ) ? " enabled " : " disabled " ) ;
2014-09-06 21:22:35 +00:00
pConsole - > Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2015-10-23 00:33:10 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " helper access for '%s' is now %s " , pResult - > GetString ( 0 ) , pCommand - > GetAccessLevel ( ) > = ACCESS_LEVEL_HELPER ? " enabled " : " disabled " ) ;
pConsole - > Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2011-08-26 07:19:00 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " user access for '%s' is now %s " , pResult - > GetString ( 0 ) , pCommand - > GetAccessLevel ( ) > = ACCESS_LEVEL_USER ? " enabled " : " disabled " ) ;
2011-07-05 19:54:10 +00:00
}
else
2011-08-26 07:19:00 +00:00
{
2011-07-14 20:07:21 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " moderator access for '%s' is %s " , pResult - > GetString ( 0 ) , pCommand - > GetAccessLevel ( ) ? " enabled " : " disabled " ) ;
2014-09-06 21:22:35 +00:00
pConsole - > Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2015-10-23 00:33:10 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " helper access for '%s' is %s " , pResult - > GetString ( 0 ) , pCommand - > GetAccessLevel ( ) > = ACCESS_LEVEL_HELPER ? " enabled " : " disabled " ) ;
pConsole - > Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2011-08-26 07:19:00 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " user access for '%s' is %s " , pResult - > GetString ( 0 ) , pCommand - > GetAccessLevel ( ) > = ACCESS_LEVEL_USER ? " enabled " : " disabled " ) ;
}
2011-07-05 19:54:10 +00:00
}
else
str_format ( aBuf , sizeof ( aBuf ) , " No such command: '%s'. " , pResult - > GetString ( 0 ) ) ;
2014-09-06 21:22:35 +00:00
pConsole - > Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2011-07-05 19:54:10 +00:00
}
2015-10-26 23:33:26 +00:00
void CConsole : : ConCommandStatus ( IResult * pResult , void * pUser )
2011-07-05 19:54:10 +00:00
{
CConsole * pConsole = static_cast < CConsole * > ( pUser ) ;
char aBuf [ 240 ] ;
mem_zero ( aBuf , sizeof ( aBuf ) ) ;
int Used = 0 ;
for ( CCommand * pCommand = pConsole - > m_pFirstCommand ; pCommand ; pCommand = pCommand - > m_pNext )
{
2015-10-26 23:33:26 +00:00
if ( pCommand - > m_Flags & pConsole - > m_FlagMask & & pCommand - > GetAccessLevel ( ) > = clamp ( pResult - > GetInteger ( 0 ) , ( int ) ACCESS_LEVEL_ADMIN , ( int ) ACCESS_LEVEL_USER ) )
2011-07-05 19:54:10 +00:00
{
int Length = str_length ( pCommand - > m_pName ) ;
if ( Used + Length + 2 < ( int ) ( sizeof ( aBuf ) ) )
{
if ( Used > 0 )
{
Used + = 2 ;
str_append ( aBuf , " , " , sizeof ( aBuf ) ) ;
}
str_append ( aBuf , pCommand - > m_pName , sizeof ( aBuf ) ) ;
Used + = Length ;
}
else
{
2014-09-06 21:22:35 +00:00
pConsole - > Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2011-07-05 19:54:10 +00:00
mem_zero ( aBuf , sizeof ( aBuf ) ) ;
str_copy ( aBuf , pCommand - > m_pName , sizeof ( aBuf ) ) ;
Used = Length ;
}
}
}
if ( Used > 0 )
2014-09-06 21:22:35 +00:00
pConsole - > Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2011-07-05 19:54:10 +00:00
}
2015-10-26 23:33:26 +00:00
void CConsole : : ConUserCommandStatus ( IResult * pResult , void * pUser )
2015-10-23 00:33:10 +00:00
{
CConsole * pConsole = static_cast < CConsole * > ( pUser ) ;
2015-10-26 23:33:26 +00:00
CResult Result ;
Result . m_pCommand = " access_status " ;
char aBuf [ 4 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " %d " , IConsole : : ACCESS_LEVEL_USER ) ;
Result . AddArgument ( aBuf ) ;
2015-10-23 00:33:10 +00:00
2015-10-26 23:33:26 +00:00
pConsole - > ConCommandStatus ( & Result , pConsole ) ;
2015-10-23 00:33:10 +00:00
}
2010-05-29 07:25:38 +00:00
struct CIntVariableData
{
IConsole * m_pConsole ;
int * m_pVariable ;
int m_Min ;
int m_Max ;
2015-07-15 12:02:21 +00:00
int m_OldValue ;
2010-05-29 07:25:38 +00:00
} ;
struct CStrVariableData
{
IConsole * m_pConsole ;
char * m_pStr ;
int m_MaxSize ;
2015-07-15 12:02:21 +00:00
char * m_pOldValue ;
2010-05-29 07:25:38 +00:00
} ;
2011-08-13 00:11:06 +00:00
static void IntVariableCommand ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CIntVariableData * pData = ( CIntVariableData * ) pUserData ;
if ( pResult - > NumArguments ( ) )
{
int Val = pResult - > GetInteger ( 0 ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
// do clamping
if ( pData - > m_Min ! = pData - > m_Max )
{
if ( Val < pData - > m_Min )
Val = pData - > m_Min ;
if ( pData - > m_Max ! = 0 & & Val > pData - > m_Max )
Val = pData - > m_Max ;
}
* ( pData - > m_pVariable ) = Val ;
2015-07-15 12:02:21 +00:00
if ( pResult - > m_ClientID ! = IConsole : : CLIENT_ID_GAME )
pData - > m_OldValue = Val ;
2010-05-29 07:25:38 +00:00
}
else
{
2015-07-15 12:02:21 +00:00
char aBuf [ 32 ] ;
2011-08-13 00:11:06 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Value: %d " , * ( pData - > m_pVariable ) ) ;
2014-09-06 21:22:35 +00:00
pData - > m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2010-05-29 07:25:38 +00:00
}
}
2011-08-13 00:11:06 +00:00
static void StrVariableCommand ( IConsole : : IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CStrVariableData * pData = ( CStrVariableData * ) pUserData ;
if ( pResult - > NumArguments ( ) )
2010-09-30 22:55:16 +00:00
{
const char * pString = pResult - > GetString ( 0 ) ;
if ( ! str_utf8_check ( pString ) )
{
char Temp [ 4 ] ;
int Length = 0 ;
while ( * pString )
{
int Size = str_utf8_encode ( Temp , static_cast < const unsigned char > ( * pString + + ) ) ;
if ( Length + Size < pData - > m_MaxSize )
{
mem_copy ( pData - > m_pStr + Length , & Temp , Size ) ;
Length + = Size ;
}
else
break ;
}
pData - > m_pStr [ Length ] = 0 ;
}
else
str_copy ( pData - > m_pStr , pString , pData - > m_MaxSize ) ;
2015-07-15 12:02:21 +00:00
if ( pResult - > m_ClientID ! = IConsole : : CLIENT_ID_GAME )
str_copy ( pData - > m_pOldValue , pData - > m_pStr , pData - > m_MaxSize ) ;
2010-09-30 22:55:16 +00:00
}
2010-05-29 07:25:38 +00:00
else
{
char aBuf [ 1024 ] ;
2011-08-13 00:11:06 +00:00
str_format ( aBuf , sizeof ( aBuf ) , " Value: %s " , pData - > m_pStr ) ;
2014-09-06 21:22:35 +00:00
pData - > m_pConsole - > Print ( IConsole : : OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2010-05-29 07:25:38 +00:00
}
}
2012-01-09 00:25:18 +00:00
void CConsole : : ConToggle ( IConsole : : IResult * pResult , void * pUser )
{
CConsole * pConsole = static_cast < CConsole * > ( pUser ) ;
char aBuf [ 128 ] = { 0 } ;
CCommand * pCommand = pConsole - > FindCommand ( pResult - > GetString ( 0 ) , pConsole - > m_FlagMask ) ;
if ( pCommand )
{
FCommandCallback pfnCallback = pCommand - > m_pfnCallback ;
void * pUserData = pCommand - > m_pUserData ;
// check for chain
if ( pCommand - > m_pfnCallback = = Con_Chain )
{
CChain * pChainInfo = static_cast < CChain * > ( pCommand - > m_pUserData ) ;
pfnCallback = pChainInfo - > m_pfnCallback ;
pUserData = pChainInfo - > m_pCallbackUserData ;
}
if ( pfnCallback = = IntVariableCommand )
{
CIntVariableData * pData = static_cast < CIntVariableData * > ( pUserData ) ;
int Val = * ( pData - > m_pVariable ) = = pResult - > GetInteger ( 1 ) ? pResult - > GetInteger ( 2 ) : pResult - > GetInteger ( 1 ) ;
str_format ( aBuf , sizeof ( aBuf ) , " %s %i " , pResult - > GetString ( 0 ) , Val ) ;
pConsole - > ExecuteLine ( aBuf ) ;
aBuf [ 0 ] = 0 ;
}
else
str_format ( aBuf , sizeof ( aBuf ) , " Invalid command: '%s'. " , pResult - > GetString ( 0 ) ) ;
}
else
str_format ( aBuf , sizeof ( aBuf ) , " No such command: '%s'. " , pResult - > GetString ( 0 ) ) ;
if ( aBuf [ 0 ] ! = 0 )
2014-09-06 21:22:35 +00:00
pConsole - > Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2012-01-09 00:25:18 +00:00
}
void CConsole : : ConToggleStroke ( IConsole : : IResult * pResult , void * pUser )
{
CConsole * pConsole = static_cast < CConsole * > ( pUser ) ;
char aBuf [ 128 ] = { 0 } ;
CCommand * pCommand = pConsole - > FindCommand ( pResult - > GetString ( 1 ) , pConsole - > m_FlagMask ) ;
if ( pCommand )
{
FCommandCallback pfnCallback = pCommand - > m_pfnCallback ;
// check for chain
if ( pCommand - > m_pfnCallback = = Con_Chain )
{
CChain * pChainInfo = static_cast < CChain * > ( pCommand - > m_pUserData ) ;
pfnCallback = pChainInfo - > m_pfnCallback ;
}
if ( pfnCallback = = IntVariableCommand )
{
int Val = pResult - > GetInteger ( 0 ) = = 0 ? pResult - > GetInteger ( 3 ) : pResult - > GetInteger ( 2 ) ;
str_format ( aBuf , sizeof ( aBuf ) , " %s %i " , pResult - > GetString ( 1 ) , Val ) ;
pConsole - > ExecuteLine ( aBuf ) ;
aBuf [ 0 ] = 0 ;
}
else
str_format ( aBuf , sizeof ( aBuf ) , " Invalid command: '%s'. " , pResult - > GetString ( 1 ) ) ;
}
else
str_format ( aBuf , sizeof ( aBuf ) , " No such command: '%s'. " , pResult - > GetString ( 1 ) ) ;
if ( aBuf [ 0 ] ! = 0 )
2014-09-06 21:22:35 +00:00
pConsole - > Print ( OUTPUT_LEVEL_STANDARD , " console " , aBuf ) ;
2012-01-09 00:25:18 +00:00
}
2010-06-18 18:32:52 +00:00
CConsole : : CConsole ( int FlagMask )
2010-05-29 07:25:38 +00:00
{
2010-06-18 18:32:52 +00:00
m_FlagMask = FlagMask ;
2011-07-05 19:54:10 +00:00
m_AccessLevel = ACCESS_LEVEL_ADMIN ;
2011-07-14 20:07:21 +00:00
m_pRecycleList = 0 ;
m_TempCommands . Reset ( ) ;
2010-08-07 18:22:25 +00:00
m_StoreCommands = true ;
m_paStrokeStr [ 0 ] = " 0 " ;
m_paStrokeStr [ 1 ] = " 1 " ;
m_ExecutionQueue . Reset ( ) ;
2010-05-29 07:25:38 +00:00
m_pFirstCommand = 0 ;
m_pFirstExec = 0 ;
2011-07-30 11:40:01 +00:00
mem_zero ( m_aPrintCB , sizeof ( m_aPrintCB ) ) ;
m_NumPrintCB = 0 ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
m_pStorage = 0 ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
// register some basic commands
2017-01-05 23:17:41 +00:00
Register ( " echo " , " r[text] " , CFGFLAG_SERVER , Con_Echo , this , " Echo the text " ) ;
2015-12-28 15:14:52 +00:00
Register ( " exec " , " r[file] " , CFGFLAG_SERVER | CFGFLAG_CLIENT , Con_Exec , this , " Execute the specified file " ) ;
2011-04-13 18:37:12 +00:00
2015-12-28 15:14:52 +00:00
Register ( " toggle " , " s[config-option] i[value 1] i[value 2] " , CFGFLAG_SERVER | CFGFLAG_CLIENT , ConToggle , this , " Toggle config value " ) ;
Register ( " +toggle " , " s[config-option] i[value 1] i[value 2] " , CFGFLAG_CLIENT , ConToggleStroke , this , " Toggle config value via keypress " ) ;
2012-01-09 00:25:18 +00:00
2015-12-28 15:14:52 +00:00
Register ( " access_level " , " s[command] ?i[accesslevel] " , CFGFLAG_SERVER , ConCommandAccess , this , " Specify command accessibility (admin = 0, moderator = 1, helper = 2, all = 3) " ) ;
Register ( " access_status " , " i[accesslevel] " , CFGFLAG_SERVER , ConCommandStatus , this , " List all commands which are accessible for admin = 0, moderator = 1, helper = 2, all = 3 " ) ;
2011-09-02 20:25:16 +00:00
Register ( " cmdlist " , " " , CFGFLAG_SERVER | CFGFLAG_CHAT , ConUserCommandStatus , this , " List all commands which are accessible for users " ) ;
2011-07-05 19:54:10 +00:00
2010-05-29 07:25:38 +00:00
// TODO: this should disappear
2011-08-13 00:11:06 +00:00
# define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \
2010-05-29 07:25:38 +00:00
{ \
2015-07-15 12:02:21 +00:00
static CIntVariableData Data = { this , & g_Config . m_ # # Name , Min , Max , Def } ; \
2011-08-13 00:11:06 +00:00
Register ( # ScriptName , " ?i " , Flags , IntVariableCommand , & Data , Desc ) ; \
2010-05-29 07:25:38 +00:00
}
2011-04-13 18:37:12 +00:00
2011-08-13 00:11:06 +00:00
# define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \
2010-05-29 07:25:38 +00:00
{ \
2015-07-15 12:02:21 +00:00
static char OldValue [ Len ] = Def ; \
static CStrVariableData Data = { this , g_Config . m_ # # Name , Len , OldValue } ; \
2011-08-13 00:11:06 +00:00
Register ( # ScriptName , " ?r " , Flags , StrVariableCommand , & Data , Desc ) ; \
2010-05-29 07:25:38 +00:00
}
2011-04-13 18:37:12 +00:00
# include "config_variables.h"
2010-05-29 07:25:38 +00:00
2011-04-13 18:37:12 +00:00
# undef MACRO_CONFIG_INT
# undef MACRO_CONFIG_STR
2011-04-09 06:41:31 +00:00
2011-08-13 00:11:06 +00:00
// DDRace
2011-03-16 13:41:26 +00:00
m_Cheated = false ;
2010-05-29 07:25:38 +00:00
}
void CConsole : : ParseArguments ( int NumArgs , const char * * ppArguments )
{
for ( int i = 0 ; i < NumArgs ; i + + )
{
// check for scripts to execute
2010-10-31 16:53:00 +00:00
if ( ppArguments [ i ] [ 0 ] = = ' - ' & & ppArguments [ i ] [ 1 ] = = ' f ' & & ppArguments [ i ] [ 2 ] = = 0 )
2010-05-29 07:25:38 +00:00
{
2010-10-31 16:53:00 +00:00
if ( NumArgs - i > 1 )
2016-05-02 19:35:32 +00:00
ExecuteFile ( ppArguments [ i + 1 ] , - 1 , true ) ;
2010-05-29 07:25:38 +00:00
i + + ;
}
2010-10-31 16:53:00 +00:00
else if ( ! str_comp ( " -s " , ppArguments [ i ] ) | | ! str_comp ( " --silent " , ppArguments [ i ] ) )
{
// skip silent param
continue ;
}
2010-05-29 07:25:38 +00:00
else
{
// search arguments for overrides
2011-08-13 00:11:06 +00:00
ExecuteLine ( ppArguments [ i ] ) ;
2010-05-29 07:25:38 +00:00
}
}
}
2011-07-14 20:07:21 +00:00
void CConsole : : AddCommandSorted ( CCommand * pCommand )
{
2011-12-30 18:12:31 +00:00
if ( ! m_pFirstCommand | | str_comp ( pCommand - > m_pName , m_pFirstCommand - > m_pName ) < = 0 )
2011-07-14 20:07:21 +00:00
{
if ( m_pFirstCommand & & m_pFirstCommand - > m_pNext )
pCommand - > m_pNext = m_pFirstCommand ;
else
pCommand - > m_pNext = 0 ;
m_pFirstCommand = pCommand ;
}
else
{
for ( CCommand * p = m_pFirstCommand ; p ; p = p - > m_pNext )
{
2011-12-30 18:12:31 +00:00
if ( ! p - > m_pNext | | str_comp ( pCommand - > m_pName , p - > m_pNext - > m_pName ) < = 0 )
2011-07-14 20:07:21 +00:00
{
pCommand - > m_pNext = p - > m_pNext ;
p - > m_pNext = pCommand ;
break ;
}
}
}
}
2011-04-13 18:37:12 +00:00
void CConsole : : Register ( const char * pName , const char * pParams ,
2015-12-28 15:14:52 +00:00
int Flags , FCommandCallback pfnFunc , void * pUser , const char * pHelp )
2010-05-29 07:25:38 +00:00
{
2011-12-29 22:36:53 +00:00
CCommand * pCommand = FindCommand ( pName , Flags ) ;
bool DoAdd = false ;
if ( pCommand = = 0 )
{
pCommand = new ( mem_alloc ( sizeof ( CCommand ) , sizeof ( void * ) ) ) CCommand ;
DoAdd = true ;
}
2010-05-29 07:25:38 +00:00
pCommand - > m_pfnCallback = pfnFunc ;
pCommand - > m_pUserData = pUser ;
2011-07-14 20:07:21 +00:00
2010-05-29 07:25:38 +00:00
pCommand - > m_pName = pName ;
2011-07-14 20:07:21 +00:00
pCommand - > m_pHelp = pHelp ;
2010-05-29 07:25:38 +00:00
pCommand - > m_pParams = pParams ;
2011-08-11 08:59:14 +00:00
2010-05-29 07:25:38 +00:00
pCommand - > m_Flags = Flags ;
2011-07-14 20:07:21 +00:00
pCommand - > m_Temp = false ;
2011-12-29 22:36:53 +00:00
if ( DoAdd )
AddCommandSorted ( pCommand ) ;
2011-08-27 15:11:39 +00:00
if ( pCommand - > m_Flags & CFGFLAG_CHAT )
pCommand - > SetAccessLevel ( ACCESS_LEVEL_USER ) ;
2011-07-14 20:07:21 +00:00
}
2015-12-28 15:14:52 +00:00
void CConsole : : RegisterTemp ( const char * pName , const char * pParams , int Flags , const char * pHelp )
2011-07-14 20:07:21 +00:00
{
CCommand * pCommand ;
if ( m_pRecycleList )
{
pCommand = m_pRecycleList ;
str_copy ( const_cast < char * > ( pCommand - > m_pName ) , pName , TEMPCMD_NAME_LENGTH ) ;
str_copy ( const_cast < char * > ( pCommand - > m_pHelp ) , pHelp , TEMPCMD_HELP_LENGTH ) ;
str_copy ( const_cast < char * > ( pCommand - > m_pParams ) , pParams , TEMPCMD_PARAMS_LENGTH ) ;
m_pRecycleList = m_pRecycleList - > m_pNext ;
}
else
{
pCommand = new ( m_TempCommands . Allocate ( sizeof ( CCommand ) ) ) CCommand ;
char * pMem = static_cast < char * > ( m_TempCommands . Allocate ( TEMPCMD_NAME_LENGTH ) ) ;
str_copy ( pMem , pName , TEMPCMD_NAME_LENGTH ) ;
pCommand - > m_pName = pMem ;
pMem = static_cast < char * > ( m_TempCommands . Allocate ( TEMPCMD_HELP_LENGTH ) ) ;
str_copy ( pMem , pHelp , TEMPCMD_HELP_LENGTH ) ;
pCommand - > m_pHelp = pMem ;
pMem = static_cast < char * > ( m_TempCommands . Allocate ( TEMPCMD_PARAMS_LENGTH ) ) ;
str_copy ( pMem , pParams , TEMPCMD_PARAMS_LENGTH ) ;
pCommand - > m_pParams = pMem ;
}
pCommand - > m_pfnCallback = 0 ;
2011-08-11 08:59:14 +00:00
pCommand - > m_pUserData = 0 ;
2010-05-29 07:25:38 +00:00
pCommand - > m_Flags = Flags ;
2011-07-14 20:07:21 +00:00
pCommand - > m_Temp = true ;
AddCommandSorted ( pCommand ) ;
}
void CConsole : : DeregisterTemp ( const char * pName )
{
if ( ! m_pFirstCommand )
return ;
CCommand * pRemoved = 0 ;
// remove temp entry from command list
if ( m_pFirstCommand - > m_Temp & & str_comp ( m_pFirstCommand - > m_pName , pName ) = = 0 )
{
pRemoved = m_pFirstCommand ;
m_pFirstCommand = m_pFirstCommand - > m_pNext ;
}
else
{
for ( CCommand * pCommand = m_pFirstCommand ; pCommand - > m_pNext ; pCommand = pCommand - > m_pNext )
if ( pCommand - > m_pNext - > m_Temp & & str_comp ( pCommand - > m_pNext - > m_pName , pName ) = = 0 )
{
pRemoved = pCommand - > m_pNext ;
pCommand - > m_pNext = pCommand - > m_pNext - > m_pNext ;
break ;
}
}
2011-08-11 08:59:14 +00:00
2011-07-14 20:07:21 +00:00
// add to recycle list
if ( pRemoved )
{
pRemoved - > m_pNext = m_pRecycleList ;
m_pRecycleList = pRemoved ;
}
}
void CConsole : : DeregisterTempAll ( )
{
// set non temp as first one
for ( ; m_pFirstCommand & & m_pFirstCommand - > m_Temp ; m_pFirstCommand = m_pFirstCommand - > m_pNext ) ;
2011-08-11 08:59:14 +00:00
2011-07-14 20:07:21 +00:00
// remove temp entries from command list
for ( CCommand * pCommand = m_pFirstCommand ; pCommand & & pCommand - > m_pNext ; pCommand = pCommand - > m_pNext )
{
CCommand * pNext = pCommand - > m_pNext ;
if ( pNext - > m_Temp )
{
for ( ; pNext & & pNext - > m_Temp ; pNext = pNext - > m_pNext ) ;
pCommand - > m_pNext = pNext ;
}
}
2011-04-13 18:37:12 +00:00
2011-07-14 20:07:21 +00:00
m_TempCommands . Reset ( ) ;
m_pRecycleList = 0 ;
2010-05-29 07:25:38 +00:00
}
2011-08-13 00:11:06 +00:00
void CConsole : : Con_Chain ( IResult * pResult , void * pUserData )
2010-05-29 07:25:38 +00:00
{
CChain * pInfo = ( CChain * ) pUserData ;
pInfo - > m_pfnChainCallback ( pResult , pInfo - > m_pUserData , pInfo - > m_pfnCallback , pInfo - > m_pCallbackUserData ) ;
}
void CConsole : : Chain ( const char * pName , FChainCommandCallback pfnChainFunc , void * pUser )
{
2010-06-18 18:32:52 +00:00
CCommand * pCommand = FindCommand ( pName , m_FlagMask ) ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
if ( ! pCommand )
{
2011-08-13 00:11:06 +00:00
char aBuf [ 256 ] ;
str_format ( aBuf , sizeof ( aBuf ) , " failed to chain '%s' " , pName ) ;
Print ( IConsole : : OUTPUT_LEVEL_DEBUG , " console " , aBuf ) ;
2010-05-29 07:25:38 +00:00
return ;
}
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
CChain * pChainInfo = ( CChain * ) mem_alloc ( sizeof ( CChain ) , sizeof ( void * ) ) ;
// store info
pChainInfo - > m_pfnChainCallback = pfnChainFunc ;
pChainInfo - > m_pUserData = pUser ;
pChainInfo - > m_pfnCallback = pCommand - > m_pfnCallback ;
pChainInfo - > m_pCallbackUserData = pCommand - > m_pUserData ;
2011-04-13 18:37:12 +00:00
2010-05-29 07:25:38 +00:00
// chain
pCommand - > m_pfnCallback = Con_Chain ;
pCommand - > m_pUserData = pChainInfo ;
}
2011-08-13 00:11:06 +00:00
void CConsole : : StoreCommands ( bool Store )
2010-08-07 18:22:25 +00:00
{
if ( ! Store )
{
2011-01-07 18:33:29 +00:00
for ( CExecutionQueue : : CQueueEntry * pEntry = m_ExecutionQueue . m_pFirst ; pEntry ; pEntry = pEntry - > m_pNext )
2011-08-13 00:11:06 +00:00
pEntry - > m_pfnCommandCallback ( & pEntry - > m_Result , pEntry - > m_pCommandUserData ) ;
2010-08-07 18:22:25 +00:00
m_ExecutionQueue . Reset ( ) ;
}
m_StoreCommands = Store ;
}
2010-05-29 07:25:38 +00:00
2011-07-14 20:07:21 +00:00
const IConsole : : CCommandInfo * CConsole : : GetCommandInfo ( const char * pName , int FlagMask , bool Temp )
2010-05-29 07:25:38 +00:00
{
2011-07-14 20:07:21 +00:00
for ( CCommand * pCommand = m_pFirstCommand ; pCommand ; pCommand = pCommand - > m_pNext )
{
if ( pCommand - > m_Flags & FlagMask & & pCommand - > m_Temp = = Temp )
{
if ( str_comp_nocase ( pCommand - > m_pName , pName ) = = 0 )
return pCommand ;
}
}
return 0 ;
2010-05-29 07:25:38 +00:00
}
2010-06-18 18:32:52 +00:00
extern IConsole * CreateConsole ( int FlagMask ) { return new CConsole ( FlagMask ) ; }
2011-08-26 21:37:10 +00:00
2015-07-15 12:02:21 +00:00
void CConsole : : ResetServerGameSettings ( )
{
# define MACRO_CONFIG_INT(Name,ScriptName,Def,Min,Max,Flags,Desc) \
{ \
2015-07-15 15:43:24 +00:00
if ( ( ( Flags ) & ( CFGFLAG_SERVER | CFGFLAG_GAME ) ) = = ( CFGFLAG_SERVER | CFGFLAG_GAME ) ) \
2015-07-15 12:02:21 +00:00
{ \
CCommand * pCommand = FindCommand ( # ScriptName , CFGFLAG_SERVER ) ; \
void * pUserData = pCommand - > m_pUserData ; \
FCommandCallback pfnCallback = pCommand - > m_pfnCallback ; \
while ( pfnCallback = = Con_Chain ) \
{ \
CChain * pChainInfo = ( CChain * ) pUserData ; \
pUserData = pChainInfo - > m_pCallbackUserData ; \
pfnCallback = pChainInfo - > m_pfnCallback ; \
} \
CIntVariableData * pData = ( CIntVariableData * ) pUserData ; \
* pData - > m_pVariable = pData - > m_OldValue ; \
} \
}
# define MACRO_CONFIG_STR(Name,ScriptName,Len,Def,Flags,Desc) \
{ \
2015-07-15 15:43:24 +00:00
if ( ( ( Flags ) & ( CFGFLAG_SERVER | CFGFLAG_GAME ) ) = = ( CFGFLAG_SERVER | CFGFLAG_GAME ) ) \
2015-07-15 12:02:21 +00:00
{ \
CCommand * pCommand = FindCommand ( # ScriptName , CFGFLAG_SERVER ) ; \
void * pUserData = pCommand - > m_pUserData ; \
FCommandCallback pfnCallback = pCommand - > m_pfnCallback ; \
while ( pfnCallback = = Con_Chain ) \
{ \
CChain * pChainInfo = ( CChain * ) pUserData ; \
pUserData = pChainInfo - > m_pCallbackUserData ; \
pfnCallback = pChainInfo - > m_pfnCallback ; \
} \
CStrVariableData * pData = ( CStrVariableData * ) pUserData ; \
str_copy ( pData - > m_pOldValue , pData - > m_pStr , pData - > m_MaxSize ) ; \
} \
}
# include "config_variables.h"
# undef MACRO_CONFIG_INT
# undef MACRO_CONFIG_STR
}
2011-09-25 16:04:29 +00:00
int CConsole : : CResult : : GetVictim ( )
{
return m_Victim ;
}
void CConsole : : CResult : : ResetVictim ( )
{
m_Victim = VICTIM_NONE ;
}
bool CConsole : : CResult : : HasVictim ( )
{
return m_Victim ! = VICTIM_NONE ;
}
void CConsole : : CResult : : SetVictim ( int Victim )
{
m_Victim = clamp < int > ( Victim , VICTIM_NONE , MAX_CLIENTS - 1 ) ;
}
void CConsole : : CResult : : SetVictim ( const char * pVictim )
{
if ( ! str_comp ( pVictim , " me " ) )
m_Victim = VICTIM_ME ;
else if ( ! str_comp ( pVictim , " all " ) )
m_Victim = VICTIM_ALL ;
else
m_Victim = clamp < int > ( str_toint ( pVictim ) , 0 , MAX_CLIENTS - 1 ) ;
}