X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=cmd.c;h=a395eed658b9a65d8c95517ed3fb53e0820de83a;hb=37c4042c3dbb546c53bc5de8d556d2469b49289e;hp=995473c6e6936a60695b13e8b1ac06d5fd28e1e9;hpb=0f80ff51ff9f369233d17b3377d3a0d34b4c8e5a;p=xonotic%2Fdarkplaces.git diff --git a/cmd.c b/cmd.c index 995473c6..a395eed6 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 ); @@ -489,6 +494,24 @@ 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"); } @@ -649,11 +672,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 +714,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 +746,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 +824,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) @@ -904,7 +936,7 @@ static char asis[] = "asis"; // just to suppress const char warnings { // 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")) @@ -1052,7 +1084,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 ); } @@ -1865,3 +1897,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(); +}