X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=cmd.c;h=bbaca649369e1e5be7b88e3251d019894db88ce0;hb=30765cee4b9bb4f0e189023788088d48a9bed7a0;hp=18cb6a13fc366e63cf2ba34bc2e0bbfc17cb2cad;hpb=0d12e67fdbdacfd9ffe88db9ae03dc995ae2d7ca;p=xonotic%2Fdarkplaces.git diff --git a/cmd.c b/cmd.c index 18cb6a13..bbaca649 100644 --- a/cmd.c +++ b/cmd.c @@ -26,6 +26,8 @@ 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; @@ -281,7 +283,8 @@ void Cbuf_Execute (void) char line[MAX_INPUTLINE]; char preprocessed[MAX_INPUTLINE]; char *firstchar; - qboolean quotes, comment; + qboolean quotes; + char *comment; // LordHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes cmd_tokenizebufferpos = 0; @@ -293,7 +296,7 @@ void Cbuf_Execute (void) text = (char *)cmd_text.data; quotes = false; - comment = false; + comment = NULL; for (i=0 ; i < cmd_text.cursize ; i++) { if(!comment) @@ -311,7 +314,7 @@ void Cbuf_Execute (void) else { if(text[i] == '/' && text[i + 1] == '/' && (i == 0 || ISWHITESPACE(text[i-1]))) - comment = true; + comment = &text[i]; if(text[i] == ';') break; // don't break if inside a quoted string or comment } @@ -329,8 +332,8 @@ void Cbuf_Execute (void) } else { - memcpy (line, text, i); - line[i] = 0; + 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 @@ -347,13 +350,15 @@ void Cbuf_Execute (void) } // execute the command line - firstchar = line + strspn(line, " \t"); + firstchar = line; + while(*firstchar && ISWHITESPACE(*firstchar)) + ++firstchar; if( - (strncmp(firstchar, "alias", 5) || (firstchar[5] != ' ' && firstchar[5] != '\t')) + (strncmp(firstchar, "alias", 5) || !ISWHITESPACE(firstchar[5])) && - (strncmp(firstchar, "bind", 4) || (firstchar[4] != ' ' && firstchar[4] != '\t')) + (strncmp(firstchar, "bind", 4) || !ISWHITESPACE(firstchar[4])) && - (strncmp(firstchar, "in_bind", 7) || (firstchar[7] != ' ' && firstchar[7] != '\t')) + (strncmp(firstchar, "in_bind", 7) || !ISWHITESPACE(firstchar[7])) ) { Cmd_PreprocessString( line, preprocessed, sizeof(preprocessed), NULL ); @@ -445,24 +450,10 @@ void Cmd_StuffCmds_f (void) Cbuf_InsertText (build); } - -/* -=============== -Cmd_Exec_f -=============== -*/ -static void Cmd_Exec_f (void) +static void Cmd_Exec(const char *filename) { char *f; - const char *filename; - - if (Cmd_Argc () != 2) - { - Con_Print("exec : execute a script file\n"); - return; - } - filename = Cmd_Argv(1); if (!strcmp(filename, "config.cfg")) { filename = CONFIGFILENAME; @@ -489,6 +480,53 @@ static void Cmd_Exec_f (void) Cbuf_InsertText ("\n"); Cbuf_InsertText (f); Mem_Free(f); + + // 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 + if (gamemode == GAME_NEHAHRA) + Cbuf_InsertText("\nsv_gameplayfix_upwardvelocityclearsongroundflag 0\nsv_gameplayfix_blowupfallenzombies 0\n\n"); + // 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. + if (gamemode == GAME_HIPNOTIC) + Cbuf_InsertText("\nsv_gameplayfix_blowupfallenzombies 0\nsys_ticrate 0.02\nsv_gameplayfix_slidemoveprojectiles 0\n\n"); + // rogue mission pack has a guardian boss that does not wake up if findradius returns one of the entities around its spawn area + if (gamemode == GAME_ROGUE) + Cbuf_InsertText("\nsv_gameplayfix_findradiusdistancetobox 0\n\n"); + if (gamemode == GAME_NEXUIZ) + Cbuf_InsertText("\nsv_gameplayfix_q2airaccelerate 1\nsv_gameplayfix_stepmultipletimes 1\n\n"); + if (gamemode == GAME_TENEBRAE) + Cbuf_InsertText("\nr_shadow_gloss 2\nr_shadow_bumpscale_basetexture 4\n\n"); +} + +/* +=============== +Cmd_Exec_f +=============== +*/ +static void Cmd_Exec_f (void) +{ + fssearch_t *s; + int i; + + if (Cmd_Argc () != 2) + { + Con_Print("exec : 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); } @@ -649,11 +687,11 @@ static void Cmd_Alias_f (void) // 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++) + for (i=2 ; i < c ; i++) { - strlcat (cmd, Cmd_Argv(i), sizeof (cmd)); - if (i != c) + if (i != 2) strlcat (cmd, " ", sizeof (cmd)); + strlcat (cmd, Cmd_Argv(i), sizeof (cmd)); } strlcat (cmd, "\n", sizeof (cmd)); @@ -691,6 +729,8 @@ static void Cmd_UnAlias_f (void) { 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) @@ -721,6 +761,7 @@ typedef struct cmd_function_s xcommand_t consolefunction; xcommand_t clientfunction; qboolean csqcfunc; + qboolean initstate; // indicates this command existed at init } cmd_function_t; static int cmd_argc; @@ -798,57 +839,63 @@ static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias return NULL; } -qboolean Cmd_QuoteString(char *out, size_t outlen, const char *in, const char *quoteset) +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) - { - *out++ = 0; - return false; - } + goto fail; *out++ = '\\'; --outlen; *out++ = '"'; --outlen; } else if(*in == '\\' && quote_backslash) { if(outlen <= 2) - { - *out++ = 0; - return false; - } + goto fail; *out++ = '\\'; --outlen; *out++ = '\\'; --outlen; } else if(*in == '$' && quote_dollar) { if(outlen <= 2) - { - *out++ = 0; - return false; - } + goto fail; *out++ = '$'; --outlen; *out++ = '$'; --outlen; } else { if(outlen <= 1) - { - *out++ = 0; - return false; - } + 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) @@ -857,6 +904,7 @@ static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t * static char varval[MAX_INPUTLINE]; const char *varstr; char *varfunc; +static char asis[] = "asis"; // just to suppress const char warnings if(varlen >= MAX_INPUTLINE) varlen = MAX_INPUTLINE - 1; @@ -887,7 +935,7 @@ static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t * varstr = Cmd_GetDirectCvarValue(varname, alias, &is_multiple); if(is_multiple) if(!varfunc) - varfunc = "asis"; + varfunc = asis; } if(!varstr) @@ -903,7 +951,7 @@ static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t * { // 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, "\"\\"); + Cmd_QuoteString(varval, sizeof(varval), varstr, "\"\\", false); return varval; } else if(!strcmp(varfunc, "asis")) @@ -1051,7 +1099,7 @@ static void Cmd_ExecuteAlias (cmdalias_t *alias) // 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, "$"); + Cmd_QuoteString(buffer2, sizeof(buffer2), buffer, "$", false); Cbuf_InsertText( buffer2 ); } @@ -1864,3 +1912,61 @@ int Cmd_CheckParm (const char *parm) return 0; } + + +void Cmd_SaveInitState(void) +{ + cmd_function_t *f; + cmdalias_t *a; + for (f = cmd_functions;f;f = f->next) + f->initstate = true; + for (a = cmd_alias;a;a = a->next) + { + a->initstate = true; + a->initialvalue = Mem_strdup(zonemempool, a->value); + } + Cvar_SaveInitState(); +} + +void Cmd_RestoreInitState(void) +{ + cmd_function_t *f, **fp; + cmdalias_t *a, **ap; + for (fp = &cmd_functions;(f = *fp);) + { + if (f->initstate) + fp = &f->next; + else + { + // destroy this command, it didn't exist at init + Con_DPrintf("Cmd_RestoreInitState: Destroying command %s\n", f->name); + *fp = f->next; + Z_Free(f); + } + } + for (ap = &cmd_alias;(a = *ap);) + { + if (a->initstate) + { + // restore this alias, it existed at init + if (strcmp(a->value ? a->value : "", a->initialvalue ? a->initialvalue : "")) + { + Con_DPrintf("Cmd_RestoreInitState: Restoring alias %s\n", a->name); + if (a->value) + Z_Free(a->value); + a->value = Mem_strdup(zonemempool, a->initialvalue); + } + ap = &a->next; + } + else + { + // free this alias, it didn't exist at init... + Con_DPrintf("Cmd_RestoreInitState: Destroying alias %s\n", a->name); + *ap = a->next; + if (a->value) + Z_Free(a->value); + Z_Free(a); + } + } + Cvar_RestoreInitState(); +}