/cmd.c
C | 2235 lines | 1949 code | 94 blank | 192 comment | 206 complexity | 81156f971c9bfbfe64bbde4defff54cf MD5 | raw file
Possible License(s): GPL-2.0
Large files files are truncated, but you can click here to view the full file
- /*
- Copyright (C) 1996-1997 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- // cmd.c -- Quake script command processing module
- #include "quakedef.h"
- #include "thread.h"
- typedef struct cmdalias_s
- {
- struct cmdalias_s *next;
- char name[MAX_ALIAS_NAME];
- char *value;
- qboolean initstate; // indicates this command existed at init
- char *initialvalue; // backup copy of value at init
- } cmdalias_t;
- static cmdalias_t *cmd_alias;
- static qboolean cmd_wait;
- static mempool_t *cmd_mempool;
- static char cmd_tokenizebuffer[CMD_TOKENIZELENGTH];
- static int cmd_tokenizebufferpos = 0;
- //=============================================================================
- /*
- ============
- Cmd_Wait_f
- Causes execution of the remainder of the command buffer to be delayed until
- next frame. This allows commands like:
- bind g "impulse 5 ; +attack ; wait ; -attack ; impulse 2"
- ============
- */
- static void Cmd_Wait_f (void)
- {
- cmd_wait = true;
- }
- typedef struct cmddeferred_s
- {
- struct cmddeferred_s *next;
- char *value;
- double delay;
- } cmddeferred_t;
- static cmddeferred_t *cmd_deferred_list = NULL;
- /*
- ============
- Cmd_Defer_f
- Cause a command to be executed after a delay.
- ============
- */
- static void Cmd_Defer_f (void)
- {
- if(Cmd_Argc() == 1)
- {
- cmddeferred_t *next = cmd_deferred_list;
- if(!next)
- Con_Printf("No commands are pending.\n");
- while(next)
- {
- Con_Printf("-> In %9.2f: %s\n", next->delay, next->value);
- next = next->next;
- }
- } else if(Cmd_Argc() == 2 && !strcasecmp("clear", Cmd_Argv(1)))
- {
- while(cmd_deferred_list)
- {
- cmddeferred_t *cmd = cmd_deferred_list;
- cmd_deferred_list = cmd->next;
- Mem_Free(cmd->value);
- Mem_Free(cmd);
- }
- } else if(Cmd_Argc() == 3)
- {
- const char *value = Cmd_Argv(2);
- cmddeferred_t *defcmd = (cmddeferred_t*)Mem_Alloc(tempmempool, sizeof(*defcmd));
- size_t len = strlen(value);
- defcmd->delay = atof(Cmd_Argv(1));
- defcmd->value = (char*)Mem_Alloc(tempmempool, len+1);
- memcpy(defcmd->value, value, len+1);
- defcmd->next = NULL;
- if(cmd_deferred_list)
- {
- cmddeferred_t *next = cmd_deferred_list;
- while(next->next)
- next = next->next;
- next->next = defcmd;
- } else
- cmd_deferred_list = defcmd;
- /* Stupid me... this changes the order... so commands with the same delay go blub :S
- defcmd->next = cmd_deferred_list;
- cmd_deferred_list = defcmd;*/
- } else {
- Con_Printf("usage: defer <seconds> <command>\n"
- " defer clear\n");
- return;
- }
- }
- /*
- ============
- Cmd_Centerprint_f
- Print something to the center of the screen using SCR_Centerprint
- ============
- */
- static void Cmd_Centerprint_f (void)
- {
- char msg[MAX_INPUTLINE];
- unsigned int i, c, p;
- c = Cmd_Argc();
- if(c >= 2)
- {
- strlcpy(msg, Cmd_Argv(1), sizeof(msg));
- for(i = 2; i < c; ++i)
- {
- strlcat(msg, " ", sizeof(msg));
- strlcat(msg, Cmd_Argv(i), sizeof(msg));
- }
- c = (unsigned int)strlen(msg);
- for(p = 0, i = 0; i < c; ++i)
- {
- if(msg[i] == '\\')
- {
- if(msg[i+1] == 'n')
- msg[p++] = '\n';
- else if(msg[i+1] == '\\')
- msg[p++] = '\\';
- else {
- msg[p++] = '\\';
- msg[p++] = msg[i+1];
- }
- ++i;
- } else {
- msg[p++] = msg[i];
- }
- }
- msg[p] = '\0';
- SCR_CenterPrint(msg);
- }
- }
- /*
- =============================================================================
- COMMAND BUFFER
- =============================================================================
- */
- static sizebuf_t cmd_text;
- static unsigned char cmd_text_buf[CMDBUFSIZE];
- void *cmd_text_mutex = NULL;
- /*
- ============
- Cbuf_AddText
- Adds command text at the end of the buffer
- ============
- */
- void Cbuf_AddText (const char *text)
- {
- int l;
- l = (int)strlen(text);
- Cbuf_LockThreadMutex();
- if (cmd_text.cursize + l >= cmd_text.maxsize)
- Con_Print("Cbuf_AddText: overflow\n");
- else
- SZ_Write(&cmd_text, (const unsigned char *)text, l);
- Cbuf_UnlockThreadMutex();
- }
- /*
- ============
- Cbuf_InsertText
- Adds command text immediately after the current command
- Adds a \n to the text
- FIXME: actually change the command buffer to do less copying
- ============
- */
- void Cbuf_InsertText (const char *text)
- {
- size_t l = strlen(text);
- Cbuf_LockThreadMutex();
- // we need to memmove the existing text and stuff this in before it...
- if (cmd_text.cursize + l >= (size_t)cmd_text.maxsize)
- Con_Print("Cbuf_InsertText: overflow\n");
- else
- {
- // we don't have a SZ_Prepend, so...
- memmove(cmd_text.data + l, cmd_text.data, cmd_text.cursize);
- cmd_text.cursize += (int)l;
- memcpy(cmd_text.data, text, l);
- }
- Cbuf_UnlockThreadMutex();
- }
- /*
- ============
- Cbuf_Execute_Deferred --blub
- ============
- */
- static void Cbuf_Execute_Deferred (void)
- {
- static double oldrealtime = 0;
- cmddeferred_t *cmd, *prev;
- double eat;
- if (realtime - oldrealtime < 0 || realtime - oldrealtime > 1800) oldrealtime = realtime;
- eat = realtime - oldrealtime;
- if (eat < (1.0 / 120.0))
- return;
- oldrealtime = realtime;
- prev = NULL;
- cmd = cmd_deferred_list;
- while(cmd)
- {
- cmd->delay -= eat;
- if(cmd->delay <= 0)
- {
- Cbuf_AddText(cmd->value);
- Cbuf_AddText(";\n");
- Mem_Free(cmd->value);
- if(prev) {
- prev->next = cmd->next;
- Mem_Free(cmd);
- cmd = prev->next;
- } else {
- cmd_deferred_list = cmd->next;
- Mem_Free(cmd);
- cmd = cmd_deferred_list;
- }
- continue;
- }
- prev = cmd;
- cmd = cmd->next;
- }
- }
- /*
- ============
- Cbuf_Execute
- ============
- */
- static qboolean Cmd_PreprocessString( const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias );
- void Cbuf_Execute (void)
- {
- int i;
- char *text;
- char line[MAX_INPUTLINE];
- char preprocessed[MAX_INPUTLINE];
- char *firstchar;
- qboolean quotes;
- char *comment;
- // LordHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes
- cmd_tokenizebufferpos = 0;
- while (cmd_text.cursize)
- {
- // find a \n or ; line break
- text = (char *)cmd_text.data;
- quotes = false;
- comment = NULL;
- for (i=0 ; i < cmd_text.cursize ; i++)
- {
- if(!comment)
- {
- if (text[i] == '"')
- quotes = !quotes;
- if(quotes)
- {
- // make sure i doesn't get > cursize which causes a negative
- // size in memmove, which is fatal --blub
- if (i < (cmd_text.cursize-1) && (text[i] == '\\' && (text[i+1] == '"' || text[i+1] == '\\')))
- i++;
- }
- else
- {
- if(text[i] == '/' && text[i + 1] == '/' && (i == 0 || ISWHITESPACE(text[i-1])))
- comment = &text[i];
- if(text[i] == ';')
- break; // don't break if inside a quoted string or comment
- }
- }
- if (text[i] == '\r' || text[i] == '\n')
- break;
- }
- // better than CRASHING on overlong input lines that may SOMEHOW enter the buffer
- if(i >= MAX_INPUTLINE)
- {
- Con_Printf("Warning: console input buffer had an overlong line. Ignored.\n");
- line[0] = 0;
- }
- else
- {
- memcpy (line, text, comment ? (comment - text) : i);
- line[comment ? (comment - text) : i] = 0;
- }
- // delete the text from the command buffer and move remaining commands down
- // this is necessary because commands (exec, alias) can insert data at the
- // beginning of the text buffer
- if (i == cmd_text.cursize)
- cmd_text.cursize = 0;
- else
- {
- i++;
- cmd_text.cursize -= i;
- memmove (cmd_text.data, text+i, cmd_text.cursize);
- }
- // execute the command line
- firstchar = line;
- while(*firstchar && ISWHITESPACE(*firstchar))
- ++firstchar;
- if(
- (strncmp(firstchar, "alias", 5) || !ISWHITESPACE(firstchar[5]))
- &&
- (strncmp(firstchar, "bind", 4) || !ISWHITESPACE(firstchar[4]))
- &&
- (strncmp(firstchar, "in_bind", 7) || !ISWHITESPACE(firstchar[7]))
- )
- {
- if(Cmd_PreprocessString( line, preprocessed, sizeof(preprocessed), NULL ))
- Cmd_ExecuteString (preprocessed, src_command, false);
- }
- else
- {
- Cmd_ExecuteString (line, src_command, false);
- }
- if (cmd_wait)
- { // skip out while text still remains in buffer, leaving it
- // for next frame
- cmd_wait = false;
- break;
- }
- }
- }
- void Cbuf_Frame(void)
- {
- Cbuf_Execute_Deferred();
- if (cmd_text.cursize)
- {
- SV_LockThreadMutex();
- Cbuf_Execute();
- SV_UnlockThreadMutex();
- }
- }
- /*
- ==============================================================================
- SCRIPT COMMANDS
- ==============================================================================
- */
- /*
- ===============
- Cmd_StuffCmds_f
- Adds command line parameters as script statements
- Commands lead with a +, and continue until a - or another +
- quake +prog jctest.qp +cmd amlev1
- quake -nosound +cmd amlev1
- ===============
- */
- qboolean host_stuffcmdsrun = false;
- static void Cmd_StuffCmds_f (void)
- {
- int i, j, l;
- // this is for all commandline options combined (and is bounds checked)
- char build[MAX_INPUTLINE];
- if (Cmd_Argc () != 1)
- {
- Con_Print("stuffcmds : execute command line parameters\n");
- return;
- }
- // no reason to run the commandline arguments twice
- if (host_stuffcmdsrun)
- return;
- host_stuffcmdsrun = true;
- build[0] = 0;
- l = 0;
- for (i = 0;i < com_argc;i++)
- {
- if (com_argv[i] && com_argv[i][0] == '+' && (com_argv[i][1] < '0' || com_argv[i][1] > '9') && l + strlen(com_argv[i]) - 1 <= sizeof(build) - 1)
- {
- j = 1;
- while (com_argv[i][j])
- build[l++] = com_argv[i][j++];
- i++;
- for (;i < com_argc;i++)
- {
- if (!com_argv[i])
- continue;
- if ((com_argv[i][0] == '+' || com_argv[i][0] == '-') && (com_argv[i][1] < '0' || com_argv[i][1] > '9'))
- break;
- if (l + strlen(com_argv[i]) + 4 > sizeof(build) - 1)
- break;
- build[l++] = ' ';
- if (strchr(com_argv[i], ' '))
- build[l++] = '\"';
- for (j = 0;com_argv[i][j];j++)
- build[l++] = com_argv[i][j];
- if (strchr(com_argv[i], ' '))
- build[l++] = '\"';
- }
- build[l++] = '\n';
- i--;
- }
- }
- // now terminate the combined string and prepend it to the command buffer
- // we already reserved space for the terminator
- build[l++] = 0;
- Cbuf_InsertText (build);
- }
- static void Cmd_Exec(const char *filename)
- {
- char *f;
- size_t filenameLen = strlen(filename);
- qboolean isdefaultcfg =
- !strcmp(filename, "default.cfg") ||
- (filenameLen >= 12 && !strcmp(filename + filenameLen - 12, "/default.cfg"));
- if (!strcmp(filename, "config.cfg"))
- {
- filename = CONFIGFILENAME;
- if (COM_CheckParm("-noconfig"))
- return; // don't execute config.cfg
- }
- f = (char *)FS_LoadFile (filename, tempmempool, false, NULL);
- if (!f)
- {
- Con_Printf("couldn't exec %s\n",filename);
- return;
- }
- Con_Printf("execing %s\n",filename);
- // if executing default.cfg for the first time, lock the cvar defaults
- // it may seem backwards to insert this text BEFORE the default.cfg
- // but Cbuf_InsertText inserts before, so this actually ends up after it.
- if (isdefaultcfg)
- Cbuf_InsertText("\ncvar_lockdefaults\n");
- // insert newline after the text to make sure the last line is terminated (some text editors omit the trailing newline)
- // (note: insertion order here is backwards from execution order, so this adds it after the text, by calling it before...)
- Cbuf_InsertText ("\n");
- Cbuf_InsertText (f);
- Mem_Free(f);
- if (isdefaultcfg)
- {
- // special defaults for specific games go here, these execute before default.cfg
- // Nehahra pushable crates malfunction in some levels if this is on
- // Nehahra NPC AI is confused by blowupfallenzombies
- switch(gamemode)
- {
- case GAME_NORMAL:
- Cbuf_InsertText("\n"
- "sv_gameplayfix_blowupfallenzombies 0\n"
- "sv_gameplayfix_findradiusdistancetobox 0\n"
- "sv_gameplayfix_grenadebouncedownslopes 0\n"
- "sv_gameplayfix_slidemoveprojectiles 0\n"
- "sv_gameplayfix_upwardvelocityclearsongroundflag 0\n"
- "sv_gameplayfix_setmodelrealbox 0\n"
- "sv_gameplayfix_droptofloorstartsolid 0\n"
- "sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 0\n"
- "sv_gameplayfix_noairborncorpse 0\n"
- "sv_gameplayfix_noairborncorpse_allowsuspendeditems 0\n"
- "sv_gameplayfix_easierwaterjump 0\n"
- "sv_gameplayfix_delayprojectiles 0\n"
- "sv_gameplayfix_multiplethinksperframe 0\n"
- "sv_gameplayfix_fixedcheckwatertransition 0\n"
- "sv_gameplayfix_q1bsptracelinereportstexture 0\n"
- "sv_gameplayfix_swiminbmodels 0\n"
- "sv_gameplayfix_downtracesupportsongroundflag 0\n"
- "sys_ticrate 0.01388889\n"
- "r_shadow_gloss 1\n"
- "r_shadow_bumpscale_basetexture 0\n"
- );
- break;
- case GAME_NEHAHRA:
- Cbuf_InsertText("\n"
- "sv_gameplayfix_blowupfallenzombies 0\n"
- "sv_gameplayfix_findradiusdistancetobox 0\n"
- "sv_gameplayfix_grenadebouncedownslopes 0\n"
- "sv_gameplayfix_slidemoveprojectiles 0\n"
- "sv_gameplayfix_upwardvelocityclearsongroundflag 0\n"
- "sv_gameplayfix_setmodelrealbox 0\n"
- "sv_gameplayfix_droptofloorstartsolid 0\n"
- "sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 0\n"
- "sv_gameplayfix_noairborncorpse 0\n"
- "sv_gameplayfix_noairborncorpse_allowsuspendeditems 0\n"
- "sv_gameplayfix_easierwaterjump 0\n"
- "sv_gameplayfix_delayprojectiles 0\n"
- "sv_gameplayfix_multiplethinksperframe 0\n"
- "sv_gameplayfix_fixedcheckwatertransition 0\n"
- "sv_gameplayfix_q1bsptracelinereportstexture 0\n"
- "sv_gameplayfix_swiminbmodels 0\n"
- "sv_gameplayfix_downtracesupportsongroundflag 0\n"
- "sys_ticrate 0.01388889\n"
- "r_shadow_gloss 1\n"
- "r_shadow_bumpscale_basetexture 0\n"
- );
- break;
- // hipnotic mission pack has issues in their 'friendly monster' ai, which seem to attempt to attack themselves for some reason when findradius() returns non-solid entities.
- // hipnotic mission pack has issues with bobbing water entities 'jittering' between different heights on alternate frames at the default 0.0138889 ticrate, 0.02 avoids this issue
- // hipnotic mission pack has issues in their proximity mine sticking code, which causes them to bounce off.
- case GAME_HIPNOTIC:
- case GAME_QUOTH:
- Cbuf_InsertText("\n"
- "sv_gameplayfix_blowupfallenzombies 0\n"
- "sv_gameplayfix_findradiusdistancetobox 0\n"
- "sv_gameplayfix_grenadebouncedownslopes 0\n"
- "sv_gameplayfix_slidemoveprojectiles 0\n"
- "sv_gameplayfix_upwardvelocityclearsongroundflag 0\n"
- "sv_gameplayfix_setmodelrealbox 0\n"
- "sv_gameplayfix_droptofloorstartsolid 0\n"
- "sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 0\n"
- "sv_gameplayfix_noairborncorpse 0\n"
- "sv_gameplayfix_noairborncorpse_allowsuspendeditems 0\n"
- "sv_gameplayfix_easierwaterjump 0\n"
- "sv_gameplayfix_delayprojectiles 0\n"
- "sv_gameplayfix_multiplethinksperframe 0\n"
- "sv_gameplayfix_fixedcheckwatertransition 0\n"
- "sv_gameplayfix_q1bsptracelinereportstexture 0\n"
- "sv_gameplayfix_swiminbmodels 0\n"
- "sv_gameplayfix_downtracesupportsongroundflag 0\n"
- "sys_ticrate 0.02\n"
- "r_shadow_gloss 1\n"
- "r_shadow_bumpscale_basetexture 0\n"
- );
- break;
- // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area
- case GAME_ROGUE:
- Cbuf_InsertText("\n"
- "sv_gameplayfix_blowupfallenzombies 0\n"
- "sv_gameplayfix_findradiusdistancetobox 0\n"
- "sv_gameplayfix_grenadebouncedownslopes 0\n"
- "sv_gameplayfix_slidemoveprojectiles 0\n"
- "sv_gameplayfix_upwardvelocityclearsongroundflag 0\n"
- "sv_gameplayfix_setmodelrealbox 0\n"
- "sv_gameplayfix_droptofloorstartsolid 0\n"
- "sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 0\n"
- "sv_gameplayfix_noairborncorpse 0\n"
- "sv_gameplayfix_noairborncorpse_allowsuspendeditems 0\n"
- "sv_gameplayfix_easierwaterjump 0\n"
- "sv_gameplayfix_delayprojectiles 0\n"
- "sv_gameplayfix_multiplethinksperframe 0\n"
- "sv_gameplayfix_fixedcheckwatertransition 0\n"
- "sv_gameplayfix_q1bsptracelinereportstexture 0\n"
- "sv_gameplayfix_swiminbmodels 0\n"
- "sv_gameplayfix_downtracesupportsongroundflag 0\n"
- "sys_ticrate 0.01388889\n"
- "r_shadow_gloss 1\n"
- "r_shadow_bumpscale_basetexture 0\n"
- );
- break;
- case GAME_TENEBRAE:
- Cbuf_InsertText("\n"
- "sv_gameplayfix_blowupfallenzombies 0\n"
- "sv_gameplayfix_findradiusdistancetobox 0\n"
- "sv_gameplayfix_grenadebouncedownslopes 0\n"
- "sv_gameplayfix_slidemoveprojectiles 0\n"
- "sv_gameplayfix_upwardvelocityclearsongroundflag 0\n"
- "sv_gameplayfix_setmodelrealbox 0\n"
- "sv_gameplayfix_droptofloorstartsolid 0\n"
- "sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 0\n"
- "sv_gameplayfix_noairborncorpse 0\n"
- "sv_gameplayfix_noairborncorpse_allowsuspendeditems 0\n"
- "sv_gameplayfix_easierwaterjump 0\n"
- "sv_gameplayfix_delayprojectiles 0\n"
- "sv_gameplayfix_multiplethinksperframe 0\n"
- "sv_gameplayfix_fixedcheckwatertransition 0\n"
- "sv_gameplayfix_q1bsptracelinereportstexture 0\n"
- "sv_gameplayfix_swiminbmodels 0\n"
- "sv_gameplayfix_downtracesupportsongroundflag 0\n"
- "sys_ticrate 0.01388889\n"
- "r_shadow_gloss 2\n"
- "r_shadow_bumpscale_basetexture 4\n"
- );
- break;
- case GAME_NEXUIZ:
- Cbuf_InsertText("\n"
- "sv_gameplayfix_blowupfallenzombies 1\n"
- "sv_gameplayfix_findradiusdistancetobox 1\n"
- "sv_gameplayfix_grenadebouncedownslopes 1\n"
- "sv_gameplayfix_slidemoveprojectiles 1\n"
- "sv_gameplayfix_upwardvelocityclearsongroundflag 1\n"
- "sv_gameplayfix_setmodelrealbox 1\n"
- "sv_gameplayfix_droptofloorstartsolid 1\n"
- "sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 1\n"
- "sv_gameplayfix_noairborncorpse 1\n"
- "sv_gameplayfix_noairborncorpse_allowsuspendeditems 1\n"
- "sv_gameplayfix_easierwaterjump 1\n"
- "sv_gameplayfix_delayprojectiles 1\n"
- "sv_gameplayfix_multiplethinksperframe 1\n"
- "sv_gameplayfix_fixedcheckwatertransition 1\n"
- "sv_gameplayfix_q1bsptracelinereportstexture 1\n"
- "sv_gameplayfix_swiminbmodels 1\n"
- "sv_gameplayfix_downtracesupportsongroundflag 1\n"
- "sys_ticrate 0.01388889\n"
- "sv_gameplayfix_q2airaccelerate 1\n"
- "sv_gameplayfix_stepmultipletimes 1\n"
- );
- break;
- // Steel Storm: Burning Retribution csqc misinterprets CSQC_InputEvent if type is a value other than 0 or 1
- case GAME_STEELSTORM:
- Cbuf_InsertText("\n"
- "sv_gameplayfix_blowupfallenzombies 1\n"
- "sv_gameplayfix_findradiusdistancetobox 1\n"
- "sv_gameplayfix_grenadebouncedownslopes 1\n"
- "sv_gameplayfix_slidemoveprojectiles 1\n"
- "sv_gameplayfix_upwardvelocityclearsongroundflag 1\n"
- "sv_gameplayfix_setmodelrealbox 1\n"
- "sv_gameplayfix_droptofloorstartsolid 1\n"
- "sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 1\n"
- "sv_gameplayfix_noairborncorpse 1\n"
- "sv_gameplayfix_noairborncorpse_allowsuspendeditems 1\n"
- "sv_gameplayfix_easierwaterjump 1\n"
- "sv_gameplayfix_delayprojectiles 1\n"
- "sv_gameplayfix_multiplethinksperframe 1\n"
- "sv_gameplayfix_fixedcheckwatertransition 1\n"
- "sv_gameplayfix_q1bsptracelinereportstexture 1\n"
- "sv_gameplayfix_swiminbmodels 1\n"
- "sv_gameplayfix_downtracesupportsongroundflag 1\n"
- "sys_ticrate 0.01388889\n"
- "cl_csqc_generatemousemoveevents 0\n"
- );
- break;
- default:
- Cbuf_InsertText("\n"
- "sv_gameplayfix_blowupfallenzombies 1\n"
- "sv_gameplayfix_findradiusdistancetobox 1\n"
- "sv_gameplayfix_grenadebouncedownslopes 1\n"
- "sv_gameplayfix_slidemoveprojectiles 1\n"
- "sv_gameplayfix_upwardvelocityclearsongroundflag 1\n"
- "sv_gameplayfix_setmodelrealbox 1\n"
- "sv_gameplayfix_droptofloorstartsolid 1\n"
- "sv_gameplayfix_droptofloorstartsolid_nudgetocorrect 1\n"
- "sv_gameplayfix_noairborncorpse 1\n"
- "sv_gameplayfix_noairborncorpse_allowsuspendeditems 1\n"
- "sv_gameplayfix_easierwaterjump 1\n"
- "sv_gameplayfix_delayprojectiles 1\n"
- "sv_gameplayfix_multiplethinksperframe 1\n"
- "sv_gameplayfix_fixedcheckwatertransition 1\n"
- "sv_gameplayfix_q1bsptracelinereportstexture 1\n"
- "sv_gameplayfix_swiminbmodels 1\n"
- "sv_gameplayfix_downtracesupportsongroundflag 1\n"
- "sys_ticrate 0.01388889\n"
- );
- break;
- }
- }
- }
- /*
- ===============
- Cmd_Exec_f
- ===============
- */
- static void Cmd_Exec_f (void)
- {
- fssearch_t *s;
- int i;
- if (Cmd_Argc () != 2)
- {
- Con_Print("exec <filename> : execute a script file\n");
- return;
- }
- s = FS_Search(Cmd_Argv(1), true, true);
- if(!s || !s->numfilenames)
- {
- Con_Printf("couldn't exec %s\n",Cmd_Argv(1));
- return;
- }
- for(i = 0; i < s->numfilenames; ++i)
- Cmd_Exec(s->filenames[i]);
- FS_FreeSearch(s);
- }
- /*
- ===============
- Cmd_Echo_f
- Just prints the rest of the line to the console
- ===============
- */
- static void Cmd_Echo_f (void)
- {
- int i;
- for (i=1 ; i<Cmd_Argc() ; i++)
- Con_Printf("%s ",Cmd_Argv(i));
- Con_Print("\n");
- }
- // DRESK - 5/14/06
- // Support Doom3-style Toggle Console Command
- /*
- ===============
- Cmd_Toggle_f
- Toggles a specified console variable amongst the values specified (default is 0 and 1)
- ===============
- */
- static void Cmd_Toggle_f(void)
- {
- // Acquire Number of Arguments
- int nNumArgs = Cmd_Argc();
- if(nNumArgs == 1)
- // No Arguments Specified; Print Usage
- Con_Print("Toggle Console Variable - Usage\n toggle <variable> - toggles between 0 and 1\n toggle <variable> <value> - toggles between 0 and <value>\n toggle <variable> [string 1] [string 2]...[string n] - cycles through all strings\n");
- else
- { // Correct Arguments Specified
- // Acquire Potential CVar
- cvar_t* cvCVar = Cvar_FindVar( Cmd_Argv(1) );
- if(cvCVar != NULL)
- { // Valid CVar
- if(nNumArgs == 2)
- { // Default Usage
- if(cvCVar->integer)
- Cvar_SetValueQuick(cvCVar, 0);
- else
- Cvar_SetValueQuick(cvCVar, 1);
- }
- else
- if(nNumArgs == 3)
- { // 0 and Specified Usage
- if(cvCVar->integer == atoi(Cmd_Argv(2) ) )
- // CVar is Specified Value; // Reset to 0
- Cvar_SetValueQuick(cvCVar, 0);
- else
- if(cvCVar->integer == 0)
- // CVar is 0; Specify Value
- Cvar_SetQuick(cvCVar, Cmd_Argv(2) );
- else
- // CVar does not match; Reset to 0
- Cvar_SetValueQuick(cvCVar, 0);
- }
- else
- { // Variable Values Specified
- int nCnt;
- int bFound = 0;
- for(nCnt = 2; nCnt < nNumArgs; nCnt++)
- { // Cycle through Values
- if( strcmp(cvCVar->string, Cmd_Argv(nCnt) ) == 0)
- { // Current Value Located; Increment to Next
- if( (nCnt + 1) == nNumArgs)
- // Max Value Reached; Reset
- Cvar_SetQuick(cvCVar, Cmd_Argv(2) );
- else
- // Next Value
- Cvar_SetQuick(cvCVar, Cmd_Argv(nCnt + 1) );
- // End Loop
- nCnt = nNumArgs;
- // Assign Found
- bFound = 1;
- }
- }
- if(!bFound)
- // Value not Found; Reset to Original
- Cvar_SetQuick(cvCVar, Cmd_Argv(2) );
- }
- }
- else
- { // Invalid CVar
- Con_Printf("ERROR : CVar '%s' not found\n", Cmd_Argv(1) );
- }
- }
- }
- /*
- ===============
- Cmd_Alias_f
- Creates a new command that executes a command string (possibly ; seperated)
- ===============
- */
- static void Cmd_Alias_f (void)
- {
- cmdalias_t *a;
- char cmd[MAX_INPUTLINE];
- int i, c;
- const char *s;
- size_t alloclen;
- if (Cmd_Argc() == 1)
- {
- Con_Print("Current alias commands:\n");
- for (a = cmd_alias ; a ; a=a->next)
- Con_Printf("%s : %s", a->name, a->value);
- return;
- }
- s = Cmd_Argv(1);
- if (strlen(s) >= MAX_ALIAS_NAME)
- {
- Con_Print("Alias name is too long\n");
- return;
- }
- // if the alias already exists, reuse it
- for (a = cmd_alias ; a ; a=a->next)
- {
- if (!strcmp(s, a->name))
- {
- Z_Free (a->value);
- break;
- }
- }
- if (!a)
- {
- cmdalias_t *prev, *current;
- a = (cmdalias_t *)Z_Malloc (sizeof(cmdalias_t));
- strlcpy (a->name, s, sizeof (a->name));
- // insert it at the right alphanumeric position
- for( prev = NULL, current = cmd_alias ; current && strcmp( current->name, a->name ) < 0 ; prev = current, current = current->next )
- ;
- if( prev ) {
- prev->next = a;
- } else {
- cmd_alias = a;
- }
- a->next = current;
- }
- // copy the rest of the command line
- cmd[0] = 0; // start out with a null string
- c = Cmd_Argc();
- for (i=2 ; i < c ; i++)
- {
- if (i != 2)
- strlcat (cmd, " ", sizeof (cmd));
- strlcat (cmd, Cmd_Argv(i), sizeof (cmd));
- }
- strlcat (cmd, "\n", sizeof (cmd));
- alloclen = strlen (cmd) + 1;
- if(alloclen >= 2)
- cmd[alloclen - 2] = '\n'; // to make sure a newline is appended even if too long
- a->value = (char *)Z_Malloc (alloclen);
- memcpy (a->value, cmd, alloclen);
- }
- /*
- ===============
- Cmd_UnAlias_f
- Remove existing aliases.
- ===============
- */
- static void Cmd_UnAlias_f (void)
- {
- cmdalias_t *a, *p;
- int i;
- const char *s;
- if(Cmd_Argc() == 1)
- {
- Con_Print("unalias: Usage: unalias alias1 [alias2 ...]\n");
- return;
- }
- for(i = 1; i < Cmd_Argc(); ++i)
- {
- s = Cmd_Argv(i);
- p = NULL;
- for(a = cmd_alias; a; p = a, a = a->next)
- {
- if(!strcmp(s, a->name))
- {
- if (a->initstate) // we can not remove init aliases
- continue;
- if(a == cmd_alias)
- cmd_alias = a->next;
- if(p)
- p->next = a->next;
- Z_Free(a->value);
- Z_Free(a);
- break;
- }
- }
- if(!a)
- Con_Printf("unalias: %s alias not found\n", s);
- }
- }
- /*
- =============================================================================
- COMMAND EXECUTION
- =============================================================================
- */
- typedef struct cmd_function_s
- {
- struct cmd_function_s *next;
- const char *name;
- const char *description;
- xcommand_t consolefunction;
- xcommand_t clientfunction;
- qboolean csqcfunc;
- qboolean initstate; // indicates this command existed at init
- } cmd_function_t;
- static int cmd_argc;
- static const char *cmd_argv[MAX_ARGS];
- static const char *cmd_null_string = "";
- static const char *cmd_args;
- cmd_source_t cmd_source;
- static cmd_function_t *cmd_functions; // possible commands to execute
- static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias, qboolean *is_multiple)
- {
- cvar_t *cvar;
- long argno;
- char *endptr;
- static char vabuf[1024]; // cmd_mutex
- if(is_multiple)
- *is_multiple = false;
- if(!varname || !*varname)
- return NULL;
- if(alias)
- {
- if(!strcmp(varname, "*"))
- {
- if(is_multiple)
- *is_multiple = true;
- return Cmd_Args();
- }
- else if(!strcmp(varname, "#"))
- {
- return va(vabuf, sizeof(vabuf), "%d", Cmd_Argc());
- }
- else if(varname[strlen(varname) - 1] == '-')
- {
- argno = strtol(varname, &endptr, 10);
- if(endptr == varname + strlen(varname) - 1)
- {
- // whole string is a number, apart from the -
- const char *p = Cmd_Args();
- for(; argno > 1; --argno)
- if(!COM_ParseToken_Console(&p))
- break;
- if(p)
- {
- if(is_multiple)
- *is_multiple = true;
- // kill pre-argument whitespace
- for (;*p && ISWHITESPACE(*p);p++)
- ;
- return p;
- }
- }
- }
- else
- {
- argno = strtol(varname, &endptr, 10);
- if(*endptr == 0)
- {
- // whole string is a number
- // NOTE: we already made sure we don't have an empty cvar name!
- if(argno >= 0 && argno < Cmd_Argc())
- return Cmd_Argv(argno);
- }
- }
- }
- if((cvar = Cvar_FindVar(varname)) && !(cvar->flags & CVAR_PRIVATE))
- return cvar->string;
- return NULL;
- }
- qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset, qboolean putquotes)
- {
- qboolean quote_quot = !!strchr(quoteset, '"');
- qboolean quote_backslash = !!strchr(quoteset, '\\');
- qboolean quote_dollar = !!strchr(quoteset, '$');
- if(putquotes)
- {
- if(outlen <= 2)
- {
- *out++ = 0;
- return false;
- }
- *out++ = '"'; --outlen;
- --outlen;
- }
- while(*in)
- {
- if(*in == '"' && quote_quot)
- {
- if(outlen <= 2)
- goto fail;
- *out++ = '\\'; --outlen;
- *out++ = '"'; --outlen;
- }
- else if(*in == '\\' && quote_backslash)
- {
- if(outlen <= 2)
- goto fail;
- *out++ = '\\'; --outlen;
- *out++ = '\\'; --outlen;
- }
- else if(*in == '$' && quote_dollar)
- {
- if(outlen <= 2)
- goto fail;
- *out++ = '$'; --outlen;
- *out++ = '$'; --outlen;
- }
- else
- {
- if(outlen <= 1)
- goto fail;
- *out++ = *in; --outlen;
- }
- ++in;
- }
- if(putquotes)
- *out++ = '"';
- *out++ = 0;
- return true;
- fail:
- if(putquotes)
- *out++ = '"';
- *out++ = 0;
- return false;
- }
- static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t *alias)
- {
- static char varname[MAX_INPUTLINE]; // cmd_mutex
- static char varval[MAX_INPUTLINE]; // cmd_mutex
- const char *varstr = NULL;
- char *varfunc;
- qboolean required = false;
- qboolean optional = false;
- static char asis[] = "asis"; // just to suppress const char warnings
- if(varlen >= MAX_INPUTLINE)
- varlen = MAX_INPUTLINE - 1;
- memcpy(varname, var, varlen);
- varname[varlen] = 0;
- varfunc = strchr(varname, ' ');
- if(varfunc)
- {
- *varfunc = 0;
- ++varfunc;
- }
- if(*var == 0)
- {
- // empty cvar name?
- if(alias)
- Con_Printf("Warning: Could not expand $ in alias %s\n", alias->name);
- else
- Con_Printf("Warning: Could not expand $\n");
- return "$";
- }
- if(varfunc)
- {
- char *p;
- // ? means optional
- while((p = strchr(varfunc, '?')))
- {
- optional = true;
- memmove(p, p+1, strlen(p)); // with final NUL
- }
- // ! means required
- while((p = strchr(varfunc, '!')))
- {
- required = true;
- memmove(p, p+1, strlen(p)); // with final NUL
- }
- // kill spaces
- while((p = strchr(varfunc, ' ')))
- {
- memmove(p, p+1, strlen(p)); // with final NUL
- }
- // if no function is left, NULL it
- if(!*varfunc)
- varfunc = NULL;
- }
- if(varname[0] == '$')
- varstr = Cmd_GetDirectCvarValue(Cmd_GetDirectCvarValue(varname + 1, alias, NULL), alias, NULL);
- else
- {
- qboolean is_multiple = false;
- // Exception: $* and $n- don't use the quoted form by default
- varstr = Cmd_GetDirectCvarValue(varname, alias, &is_multiple);
- if(is_multiple)
- if(!varfunc)
- varfunc = asis;
- }
- if(!varstr)
- {
- if(required)
- {
- if(alias)
- Con_Printf("Error: Could not expand $%s in alias %s\n", varname, alias->name);
- else
- Con_Printf("Error: Could not expand $%s\n", varname);
- return NULL;
- }
- else if(optional)
- {
- return "";
- }
- else
- {
- if(alias)
- Con_Printf("Warning: Could not expand $%s in alias %s\n", varname, alias->name);
- else
- Con_Printf("Warning: Could not expand $%s\n", varname);
- dpsnprintf(varval, sizeof(varval), "$%s", varname);
- return varval;
- }
- }
- if(!varfunc || !strcmp(varfunc, "q")) // note: quoted form is default, use "asis" to override!
- {
- // quote it so it can be used inside double quotes
- // we just need to replace " by \", and of course, double backslashes
- Cmd_QuoteString(varval, sizeof(varval), varstr, "\"\\", false);
- return varval;
- }
- else if(!strcmp(varfunc, "asis"))
- {
- return varstr;
- }
- else
- Con_Printf("Unknown variable function %s\n", varfunc);
- return varstr;
- }
- /*
- Cmd_PreprocessString
- Preprocesses strings and replaces $*, $param#, $cvar accordingly. Also strips comments.
- */
- static qboolean Cmd_PreprocessString( const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias ) {
- const char *in;
- size_t eat, varlen;
- unsigned outlen;
- const char *val;
- // don't crash if there's no room in the outtext buffer
- if( maxoutlen == 0 ) {
- return false;
- }
- maxoutlen--; // because of \0
- in = intext;
- outlen = 0;
- while( *in && outlen < maxoutlen ) {
- if( *in == '$' ) {
- // this is some kind of expansion, see what comes after the $
- in++;
- // The console does the following preprocessing:
- //
- // - $$ is transformed to a single dollar sign.
- // - $var or ${var} are expanded to the contents of the named cvar,
- // with quotation marks and backslashes quoted so it can safely
- // be used inside quotation marks (and it should always be used
- // that way)
- // - ${var asis} inserts the cvar value as is, without doing this
- // quoting
- // - ${var ?} silently expands to the empty string if
- // $var does not exist
- // - ${var !} fails expansion and executes nothing if
- // $var does not exist
- // - prefix the cvar name with a dollar sign to do indirection;
- // for example, if $x has the value timelimit, ${$x} will return
- // the value of $timelimit
- // - when expanding an alias, the special variable name $* refers
- // to all alias parameters, and a number refers to that numbered
- // alias parameter, where the name of the alias is $0, the first
- // parameter is $1 and so on; as a special case, $* inserts all
- // parameters, without extra quoting, so one can use $* to just
- // pass all parameters around. All parameters starting from $n
- // can be referred to as $n- (so $* is equivalent to $1-).
- // - ${* q} and ${n- q} force quoting anyway
- //
- // Note: when expanding an alias, cvar expansion is done in the SAME step
- // as alias expansion so that alias parameters or cvar values containing
- // dollar signs have no unwanted bad side effects. However, this needs to
- // be accounted for when writing complex aliases. For example,
- // alias foo "set x NEW; echo $x"
- // actually expands to
- // "set x NEW; echo OLD"
- // and will print OLD! To work around this, use a second alias:
- // alias foo "set x NEW; foo2"
- // alias foo2 "echo $x"
- //
- // Also note: lines starting with alias are exempt from cvar expansion.
- // If you want cvar expansion, write "alias" instead:
- //
- // set x 1
- // alias foo "echo $x"
- // "alias" bar "echo $x"
- // set x 2
- //
- // foo will print 2, because the variable $x will be expanded when the alias
- // gets expanded. bar will print 1, because the variable $x was expanded
- // at definition time. foo can be equivalently defined as
- //
- // "alias" foo "echo $$x"
- //
- // because at definition time, $$ will get replaced to a single $.
- if( *in == '$' ) {
- val = "$";
- eat = 1;
- } else if(*in == '{') {
- varlen = strcspn(in + 1, "}");
- if(in[varlen + 1] == '}')
- {
- val = Cmd_GetCvarValue(in + 1, varlen, alias);
- if(!val)
- return false;
- eat = varlen + 2;
- }
- else
- {
- // ran out of data?
- val = NULL;
- eat = varlen + 1;
- }
- } else {
- varlen = strspn(in, "#*0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-");
- val = Cmd_GetCvarValue(in, varlen, alias);
- if(!val)
- return false;
- eat = varlen;
- }
- if(val)
- {
- // insert the cvar value
- while(*val && outlen < maxoutlen)
- outtext[outlen++] = *val++;
- in += eat;
- }
- else
- {
- // copy the unexpanded text
- outtext[outlen++] = '$';
- while(eat && outlen < maxoutlen)
- {
- outtext[outlen++] = *in++;
- --eat;
- }
- }
- }
- else
- outtext[outlen++] = *in++;
- }
- outtext[outlen] = 0;
- return true;
- }
- /*
- ============
- Cmd_ExecuteAlias
- Called for aliases and fills in the alias into the cbuffer
- ============
- */
- static void Cmd_ExecuteAlias (cmdalias_t *alias)
- {
- static char buffer[ MAX_INPUTLINE ]; // cmd_mutex
- static char buffer2[ MAX_INPUTLINE ]; // cmd_mutex
- qboolean ret = Cmd_PreprocessString( alias->value, buffer, sizeof(buffer) - 2, alias );
- if(!ret)
- return;
- // insert at start of command buffer, so that aliases execute in order
- // (fixes bug introduced by Black on 20050705)
- // Note: Cbuf_PreprocessString will be called on this string AGAIN! So we
- // have to make sure that no second variable expansion takes place, otherwise
- // alias parameters containing dollar signs can have bad effects.
- Cmd_QuoteString(buffer2, sizeof(buffer2), buffer, "$", false);
- Cbuf_InsertText( buffer2 );
- }
- /*
- ========
- Cmd_List
- CmdList Added by EvilTypeGuy eviltypeguy@qeradiant.com
- Thanks to Matthias "Maddes" Buecher, http://www.inside3d.com/qip/
- ========
- */
- static void Cmd_List_f (void)
- {
- cmd_function_t *cmd;
- const char *partial;
- size_t len;
- int count;
- qboolean ispattern;
- if (Cmd_Argc() > 1)
- {
- partial = Cmd_Argv (1);
- len = strlen(partial);
- ispattern = (strchr(partial, '*') || strchr(partial, '?'));
- }
- else
- {
- partial = NULL;
- len = 0;
- ispattern = false;
- }
- count = 0;
- for (cmd = cmd_functions; cmd; cmd = cmd->next)
- {
- if (partial && (ispattern ? !matchpattern_with_separator(cmd->name, partial, false, "", false) : strncmp(partial, cmd->name, len)))
- continue;
- Con_Printf("%s : %s\n", cmd->name, cmd->description);
- count++;
- }
- if (len)
- {
- if(ispattern)
- Con_Printf("%i Command%s matching \"%s\"\n\n", count, (count > 1) ? "s" : "", partial);
- else
- Con_Printf("%i Command%s beginning with \"%s\"\n\n", count, (count > 1) ? "s" : "", partial);
- }
- else
- Con_Printf("%i Command%s\n\n", count, (count > 1) ? "s" : "");
- }
- static void Cmd_Apropos_f(void)
- {
- cmd_function_t *cmd;
- cvar_t *cvar;
- cmdalias_t *alias;
- const char *partial;
- int count;
- qboolean ispattern;
- char vabuf[1024];
- if (Cmd_Argc() > 1)
- partial = Cmd_Args();
- else
- {
- Con_Printf("usage: apropos <string>\n");
- return;
- }
- ispattern = partial && (strchr(partial, '*') || strchr(partial, '?'));
- if(!ispattern)
- partial = va(vabuf, sizeof(vabuf), "*%s*", partial);
- count = 0;
- for (cvar = cvar_vars; cvar; cvar = cvar->next)
- {
- if (!matchpattern_with_separator(cvar->name, partial, true, "", false))
- if (!matchpattern_with_separator(cvar->description, partial, true, "", false))
- continue;
- Con_Printf ("cvar ^3%s^7 is \"%s\" [\"%s\"] %s\n", cvar->name, cvar->string, cvar->defstring, cvar->description);
- count++;
- }
- for (cmd = cmd_functions; cmd; cmd = cmd->next)
- {
- if (!matchpattern_with_separator(cmd->name, partial, true, "", false))
- if (!matchpattern_with_separator(cmd->description, partial, true, "", false))
- continue;
- Con_Printf("command ^2%s^7: %s\n", cmd->name, cmd->description);
- count++;
- }
- for (alias = cmd_alias; alias; alias = alias->next)
- {
- // procede here a bit differently as an alias value always got a final \n
- if (!matchpattern_with_separator(alias->name, partial, true, "", false))
- if (!matchpattern_with_separator(alias->value, partial, true, "\n", false)) // when \n is as separator wildcards don't match it
- continue;
- Con_Printf("alias ^5%s^7: %s", alias->name, alias->value); // do not print an extra \n
- count++;
- }
- Con_Printf("%i result%s\n\n", count, (count > 1) ? "s" : "");
- }
- /*
- ============
- Cmd_Init
- ============
- */
- void Cmd_Init (void)
- {
- cmd_mempool = Mem_AllocPool("commands", 0, NULL);
- // space for commands and script files
- cmd_text.data = cmd_text_buf;
- cmd_text.maxsize = sizeof(cmd_text_buf);
- cmd_text.cursize = 0;
- if (Thread_HasThreads())
- cmd_text_mutex = Thread_CreateMutex();
- }
- void Cmd_Init_Commands (void)
- {
- //
- // register our commands
- //
- Cmd_AddCommand ("stuffcmds",Cmd_StuffCmds_f, "execute commandline parameters (must be present in quake.rc script)");
- Cmd_AddCommand ("exec",Cmd_Exec_f, "execute a script file");
- Cmd_AddCommand ("echo",Cmd_Echo_f, "print a message to the console (useful in scripts)");
- Cmd_AddCommand ("alias",Cmd_Alias_f, "create a script function (parameters are passed in as $X (being X a number), $* for all parameters, $X- for all parameters starting from $X). Without arguments show the list of all alias");
- Cmd_AddCommand ("unalias",Cmd_UnAlias_f, "remove an alias");
- Cmd_AddCommand ("cmd", Cmd_ForwardToServer, "send a console commandline to the server (used by some mods)");
- Cmd_AddCommand ("wait", Cmd_Wait_f, "make script execution wait for next rendered frame");
- Cmd_AddCommand ("set", Cvar_Set_f, "create or change the value of a console variable");
- Cmd_AddCommand ("seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg");
- Cmd_AddCommand ("unset", Cvar_Del_f, "delete a cvar (does not work for static ones like _cl_name, or read-only ones)");
- #ifdef FILLALLCVARSWITHRUBBISH
- Cmd_AddCommand ("fillallcvarswithrubbish", Cvar_FillAll_f, "fill all cvars with a specified number of characters to provoke buffer overruns");
- #endif /* FILLALLCVARSWITHRUBBISH */
- // 2000-01-09 CmdList, CvarList commands By Matthias "Maddes" Buecher
- // Added/Modified by EvilTypeGuy eviltypeguy@qeradiant.com
- Cmd_AddCommand ("cmdlist", Cmd_List_f, "lists all console commands beginning with the specified prefix or matching the specified wildcard pattern");
- Cmd_AddCommand ("cvarlist", Cvar_List_f, "lists all console variables beginning with the specified prefix or matching the specified wildcard pattern");
- Cmd_AddCommand ("apropos", Cmd_Apropos_f, "lists all console variables/commands/aliases containing the specified string in the name or description");
- Cmd_AddCommand ("cvar_lockdefaults", Cvar_LockDefaults_f, "stores the current values of all cvars into their default values, only used once during startup after parsing default.cfg");
- Cmd_AddCommand ("cvar_resettodefaults_all", Cvar_ResetToDefaults_All_f, "sets all cvars to their locked default values");
- Cmd_AddCommand ("cvar_resettodefaults_nosaveonly", Cvar_ResetToDefaults_NoSaveOnly_f, "sets all non-saved cvars to their locked default values (variables that will not be saved to config.cfg)");
- Cmd_AddCommand ("cvar_resettodefaults_saveonly", Cvar_ResetToDefaults_SaveOnly_f, "sets all saved cvars to their locked default values (variables that will be saved to config.cfg)");
- Cmd_AddCommand ("cprint", Cmd_Centerprint_f, "print something at the screen center");
- Cmd_AddCommand ("defer", Cmd_Defer_f, "execute a command in the future");
- // DRESK - 5/14/06
- // Support Doom3-style Toggle Command
- Cmd_AddCommand( "toggle", Cmd_Toggle_f, "toggles a console variable's values (use for more info)");
- }
- /*
- ============
- Cmd_Shutdown
- ============
- */
- void Cmd_Shutdown(void)
- {
- if (cmd_text_mutex)
- {
- // we usually have this locked when we get here from Host_Quit_f
- Cbuf_UnlockThreadMutex();
- Thread_DestroyMutex(cmd_text_mutex);
- }
- cmd_text_mutex = NULL;
- Mem_FreePool(&cmd_mempool);
- }
- /*
- ============
- Cmd_Argc
- ============
- */
- int Cmd_Argc (void)
- {
- return cmd_argc;
- }
- /*
- ============
- Cmd_Argv
- ============
- */
- const char *Cmd_Argv (int arg)
- {
- if (arg >= cmd_argc )
- return cmd_null_string;
- return cmd_argv[arg];
- }
- /*
- ============
- Cmd_Args
- ============
- */
- const char *Cmd_Args (void)
- {
- return cmd_args;
- }
- /*
- ============
- Cmd_TokenizeString
- Parses the given string into command line tokens.
- ============
- */
- // AK: This function should only be called from ExcuteString because the current design is a bit of an hack
- static void Cmd_TokenizeString (const char *text)
- {
- int l;
- cmd_argc = 0;
- cmd_args = NULL;
- while (1)
- {
- // skip whitespace up to a /n
- while (*text && ISWHITESPACE(*text) && *text != '\r' && *text != '\n')
- text++;
- // line endings:
- // UNIX: \n
- // Mac: \r
- // Windows: \r\n
- if (*text == '\n' || *text == '\r')
- {
- // a newline separates commands in the buffer
- if (*text == '\r' && text[1] == '\n')
- text++;
- text++;
- break;
- }
- if (!*text)
- return;
- if (cmd_argc == 1)
- cmd_args = text;
- if (!COM_ParseToken_Console(&text))
- return;
- if (cmd_argc < MAX_ARGS)
- {
- l = (int)strlen(com_token) + 1;
- if (cmd_tokenizebufferpos + l > CMD_TOKENIZELENGTH)
- {
- Con_Printf("Cmd_TokenizeString: ran out of %i character buffer space for command arguements\n", CMD_TOKENIZELENGTH);
- break;
- }
- memcpy (cmd_tokenizebuffer + cmd_tokenizebufferpos, com_token, l);
- cmd_argv[cmd_argc] = cmd_tokenizebuffer + cmd_tokenizebufferpos;
- cmd_tokenizebufferpos += l;
- cmd_argc++;
- }
- }
- }
- /*
- ============
- Cmd_AddCommand
- ============
- */
- void Cmd_AddCommand_WithClientCommand (const char *cmd_name, xcommand_t consolefunction, xcommand_t clientfunction, const char *description)
- {
- cmd_function_t *cmd;
- cmd_function_t *prev, *current;
- // fail if the command is a variable name
- if (Cvar_FindVar( cmd_name ))
- {
- Con_Printf("Cmd_AddCommand: %s already defined as a var\n", cmd_name);
- return;
- }
- // fail if the command already exists
- for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
- {
- if (!strcmp (cmd_name, cmd->name))
- {
- if (consolefunction || clientfunction)
- {
- Con_Printf("Cmd_AddCommand: %s already defined\n", cmd_name);
- return;
- }
- else //[515]: csqc
- {
- cmd->csqcfunc = true;
- return;
- }
- }
- }
- cmd = (cmd_function_t *)Mem_Alloc(cmd_mempool, sizeof(cmd_function_t));
- cmd->name = cmd_name;
- cmd->consolefunction = consolefunction;
- cmd->clientfunction = clientfunction;
- cmd->description = description;
- if(!consolefunction && !clientfunction) //[515]: csqc
- cmd->csqcfunc = true;
- cmd->next = cmd_functions;
- // insert it at the right alphanumeric position
- for( prev = NULL, current = cmd_functions ; current && strcmp( current->name, cmd->name ) < 0 ; prev = current, current = current->next )
- ;
- if( prev ) {
- prev->next = cmd;
- } else {
- cmd_functions = cmd;
- }
- cmd->next = current;
- }
- void Cmd_AddCommand (const char *cmd_name, xcommand_t function, const char *description)
- {
- Cmd_AddCommand_WithClientCommand (cmd_name, function, NULL, description);
- }
- /*
- ============
- Cmd_Exists
- ============
- */
- qboolean Cmd_Exists (const char *cmd_name)
- {
- cmd_function_t *cmd;
- for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
- if (!strcmp (cmd_name,cmd->name))
- return true;
- return false;
- }
- /*
- ============
- Cmd_CompleteCommand
- ============
- */
- const char *Cmd_CompleteCommand (const char *partial)
- {
- cmd_function_t *cmd;
- size_t len;
- len = strlen(partial);
- if (!len)
- return NULL;
- // check functions
- for (cmd = cmd_functions; cmd; cmd = cmd->next)
- if (!strncasecmp(partial, cmd->name, len))
- return cmd->name;
- return NULL;
- }
- /*
- Cmd_CompleteCountPossible
- New function for tab-completion system
- Added by EvilTypeGuy
- Thanks to Fett erich@heintz.com
- Thanks to taniwha
- */
- int Cmd_CompleteCountPossible (const char *partial)
- {
- cmd_function_t *cmd;
- size_t len;
- int h;
- h = 0;
- len = strlen(partial);
- if (!len)
- return 0;
- // Loop through the command list and count all partial matches
- for (cmd = cmd_functions; cmd; cmd = cmd->next)
- if (!strncasecmp(partial, cmd->name, len))
- h++;
- return h;
- }
- /*
- Cmd_CompleteBuildList
- New function for tab-completion system
- Added by EvilTypeGuy
- Thanks to Fett erich@heintz.com
- Thanks to taniwha
- */
- const char **Cmd_CompleteBuildList (const char *partial)
- {
- cmd_function_t *cmd;
- size_t len = 0;
- size_t bpos = 0;
- size_t sizeofbuf = (Cmd_CompleteCountPossible (partial) + 1) * sizeof (const char *);
- const char **buf;
- len = strlen(partial);
- buf = (const char **)Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *));
- // Loop through the alias list and print all matches
- for (cmd = cmd_functions; cmd; cmd = cmd->next)
- if (!strncasecmp(partial, cmd->name, len))
- buf[bpos++] = cmd->name;
- buf[bpos] = NULL;
- return buf;
- }
- // written by LordHavoc
- void Cmd_CompleteCommandPrint (const char *partial)
- {
- cmd_function_t *cmd;
- size_t len = strlen(partial);
- // Loop through the command list and print all matches
- for (cmd = cmd_functions; cmd; cmd = cmd->next)
- if (!strncasecmp(partial, cmd->name, len))
- Con_Printf("^2%s^7: %s\n", cmd->name, cmd->description);
- }
- /*
- Cmd_CompleteAlias
- New function for tab-completion system
- Added by EvilTypeGuy
- Thanks to Fett erich@heintz.com
- Thanks to taniwha
- */
- const char *Cmd_CompleteAlias (const char *partial)
- {
- cmdalias_t *alias;
- size_t len;
- len = strlen(partial);
- if (!len)
- return NULL;
- // Check functions
- for (alias = cmd_alias; alias; alias = alias->next)
- if (!strncasecmp(partial, alias->name, len))
- return alias->name;
- return NULL;
- }
- // written by LordHavoc
- void Cmd_CompleteAliasPrint (const char *partial)
- {
- cmdalias_t *alias;
- size_t len = strlen(partial);
- // Loop through the alias list and print all matches
- for (alias = cmd_alias; alias; alias = alias->next)
- if (!strncasecmp(partial, alias->name, len))
- Con_Printf("^5%s^7: %s", alias->name, alias->value);
- }
- /*
- Cmd_CompleteAliasCountPossible
- New function for tab-completion system
- Added by EvilTypeGuy
- Thanks to Fett erich@heintz.com
- Thanks to taniwha
- */
- int Cmd_CompleteAliasCountPossible (const char *partial)
- {
- cmdalias_t *alias;
- size_t len;
- int h;
- h = 0;
- len = strlen(partial);
- if (!len)
- return 0;
- // Loop through the command list and count all partial matches
- for (alias = cmd_alias; alias; alias = alias->next)
- if (!strncasecmp(partial, alias->name, len))
- h++;
- return h;
- }
- /*
- Cmd_CompleteAliasBuildList
- New function for tab-completion system
- Added by EvilTypeGuy
- Thanks to Fett erich@heintz.com
- Thanks to taniwha
- */
- const char **Cmd_CompleteAliasBuildList (const char *partial)
- {
- cmdalias_t *alias;
- size_t len = 0;
- size_t bpos = 0;
- size_t sizeofbuf = (Cmd_CompleteAliasCountPossible (partial) + 1) * sizeof (const char *);
- const char **buf;
- len = strlen(partial);
- buf = (const char **)Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *));
- // Loop through the alias list and print all matches
- for (alias = cmd_alias; alias; alias = alias->next)
- if (!strncasecmp(partial, alias->name, len))
- buf[bpos++] = alias->name;
- buf[bpos] = NULL;
- return buf;
- }
- void Cmd_ClearCsqcFuncs (void)
- {
- cmd_function_t *cmd;
- for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
- cmd->csqcfunc = false;
- }
- /*
- ============
- Cmd_ExecuteString
- A complete command line has been parsed, so try to execute it
- FIXME: lookupnoadd the token to speed search?
- ============
- */
- void Cmd_ExecuteString (const char *text, cmd_source_t src, qboolean lockmutex)
- {
- int oldpos;
- int found;
- cmd_function_t *cmd;
- cmdalias_t *a;
- if (lockmutex)
- Cbuf_LockThreadMutex();
- oldpos = cmd_tokenizebufferpos;
- cmd_source = src;
- found = false;
- Cmd_TokenizeString (text);
- // execute the command line
- if (!Cmd_Argc())
- goto done; // no tokens
- // check functions
- for (cmd=cmd_functions ; cmd ; cmd=cmd->next)
- {
- if (!strcasecmp (cmd_argv[0],cmd->name))
- {
- if (cmd->csqcfunc && CL_VM_ConsoleCommand (text)) //[515]: csqc
- goto done;
- switch (src)
- {
- case src_command:
- if (cmd->consolefunction)
- cmd->consolefunction ();
- else if (cmd->clientfunction)
- {
- if (cls.state == ca_connected)
- {
- // forward remote commands to the server for execution
- Cmd_ForwardToServer();
- }
- else
- Con_Printf("Can not send command \"%s\", not connected.\n", Cmd_Argv(0));
- }
- else
- Con_Printf("Command \"%s\" can not be executed\n", Cmd_Argv(0));
- found = true;
- goto command_found;
- case src_client:
- if (cmd->clientfunction)
- {
- cmd->clientfunction ();
- goto done;
- }
- break;
- }
- break;
- }
- }
- comman…
Large files files are truncated, but you can click here to view the full file