View Single Post
A fix for FakeClientCommand() code.
Old
  (#1)
Whistler
Summoner
 
Whistler's Avatar
 
Status: Offline
Posts: 1,499
Join Date: Feb 2004
Location: Mist Village
Default A fix for FakeClientCommand() code. - 05-08-2004

Code:
void CGeneral::FakeClientCommand(CClient *pClient, const char *fmt, ...)
{
   if (!pClient->Valid())
      return; // reliability check

   edict_t *pFakeClient = pClient->edict();

   va_list argptr;
   char command[256];
   int length, fieldstart, fieldstop, i, index, stringindex = 0;

   // concatenate all the arguments in one string
   va_start(argptr, fmt);
   _vsnprintf(command, sizeof(command), fmt, argptr);
   va_end(argptr);

   if (*command == 0)
      return; // if nothing in the command buffer, return

   m_bIsFakeClientCommand = TRUE; // set the "fakeclient command" flag
   length = strlen(command); // get the total length of the command string

   // process all individual commands (separated by a semicolon) one each a time
   while (stringindex < length) {
      fieldstart = stringindex; // save field start position (first character)
      while (stringindex < length && command[stringindex] != ';')
         stringindex++; // reach end of field
      if (command[stringindex - 1] == '\n')
         fieldstop = stringindex - 2; // discard any trailing '\n' if needed
      else
         fieldstop = stringindex - 1; // save field stop position (last character before semicolon or end)
      for (i = fieldstart; i <= fieldstop; i++)
         m_szCmdArgv[i - fieldstart] = command[i]; // store the field value in the g_argv global string
      m_szCmdArgv[i - fieldstart] = 0; // terminate the string
      stringindex++; // move the overall string index one step further to bypass the semicolon

      index = 0;
      m_iCmdArgc = 0; // let's now parse that command and count the different arguments
+      m_pszCmdArgs = "";

      // count the number of arguments
      while (index < i - fieldstart) {
         while (index < i - fieldstart && m_szCmdArgv[index] == ' ')
            index++; // ignore spaces

+         if (m_iCmdArgc == 1) {
+            m_pszCmdArgs = &m_szCmdArgv[index];
+         }

         // is this field a group of words between quotes or a single word ?
         if (m_szCmdArgv[index] == '"') {
            index++; // move one step further to bypass the quote
            while (index < i - fieldstart && m_szCmdArgv[index] != '"')
               index++; // reach end of field
            index++; // move one step further to bypass the quote
         } else {
            while (index < i - fieldstart && m_szCmdArgv[index] != ' ')
               index++; // this is a single word, so reach the end of field
         }

         m_iCmdArgc++; // we have processed one argument more
      }

      ClientCommand(pFakeClient); // tell now the MOD DLL to execute this ClientCommand...
   }

   m_szCmdArgv[0] = 0; // when it's done, reset the g_argv field
   m_bIsFakeClientCommand = FALSE; // reset the "fakeclient command" flag
   m_iCmdArgc = 0; // and the argument count
}
...and:
Code:
const char *pfnCmd_Args(void)
{
   if (g_General.IsFakeClientCommand())
      return g_General.m_pszArgs;
   return (*g_engfuncs.pfnCmd_Args)();
}
m_pszCmdArgs is (char *m_pszCmdArgs

Note that the pfnCmd_Args() isn't supposed to return the command name (not only "say" "say_team" but also whatever command name). It isn't "bug in HL engine". You can look at the cmd.c file in Quake1 source code to find it out.

PS, This is PMB's code, however botman's original one also has this bug. It won't affect too much to CS, but if some MOD use pfnCmd_Args() to do something this will cause problem for bots.
  
Reply With Quote