X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=cmd.c;h=cab160b4220a10811d322d70d960b1d3474c95cf;hp=8efe3dc9a0e69290ebf36383366b94ed89130b1f;hb=2075ae43356d724bae305ce8fd36ea570718b14a;hpb=66a10ad8f7213d8969fc53f69f1ff712f3aea004 diff --git a/cmd.c b/cmd.c index 8efe3dc9..cab160b4 100644 --- a/cmd.c +++ b/cmd.c @@ -142,7 +142,7 @@ static void Cmd_Centerprint_f (void) strlcat(msg, " ", sizeof(msg)); strlcat(msg, Cmd_Argv(i), sizeof(msg)); } - c = strlen(msg); + c = (unsigned int)strlen(msg); for(p = 0, i = 0; i < c; ++i) { if(msg[i] == '\\') @@ -177,9 +177,6 @@ static sizebuf_t cmd_text; static unsigned char cmd_text_buf[CMDBUFSIZE]; void *cmd_text_mutex = NULL; -#define Cbuf_LockThreadMutex() (cmd_text_mutex ? Thread_LockMutex(cmd_text_mutex),1 : 0) -#define Cbuf_UnlockThreadMutex() (cmd_text_mutex ? Thread_UnlockMutex(cmd_text_mutex),1 : 0) - /* ============ Cbuf_AddText @@ -222,7 +219,7 @@ void Cbuf_InsertText (const char *text) { // we don't have a SZ_Prepend, so... memmove(cmd_text.data + l, cmd_text.data, cmd_text.cursize); - cmd_text.cursize += l; + cmd_text.cursize += (int)l; memcpy(cmd_text.data, text, l); } Cbuf_UnlockThreadMutex(); @@ -275,7 +272,7 @@ static void Cbuf_Execute_Deferred (void) Cbuf_Execute ============ */ -static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias ); +static qboolean Cmd_PreprocessString( const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias ); void Cbuf_Execute (void) { int i; @@ -289,7 +286,6 @@ void Cbuf_Execute (void) // LordHavoc: making sure the tokenizebuffer doesn't get filled up by repeated crashes cmd_tokenizebufferpos = 0; - Cbuf_Execute_Deferred(); while (cmd_text.cursize) { // find a \n or ; line break @@ -361,8 +357,8 @@ void Cbuf_Execute (void) (strncmp(firstchar, "in_bind", 7) || !ISWHITESPACE(firstchar[7])) ) { - Cmd_PreprocessString( line, preprocessed, sizeof(preprocessed), NULL ); - Cmd_ExecuteString (preprocessed, src_command, false); + if(Cmd_PreprocessString( line, preprocessed, sizeof(preprocessed), NULL )) + Cmd_ExecuteString (preprocessed, src_command, false); } else { @@ -378,6 +374,17 @@ void Cbuf_Execute (void) } } +void Cbuf_Frame(void) +{ + Cbuf_Execute_Deferred(); + if (cmd_text.cursize) + { + SV_LockThreadMutex(); + Cbuf_Execute(); + SV_UnlockThreadMutex(); + } +} + /* ============================================================================== @@ -453,7 +460,10 @@ static void Cmd_StuffCmds_f (void) static void Cmd_Exec(const char *filename) { char *f; - qboolean isdefaultcfg = strlen(filename) >= 11 && !strcmp(filename + strlen(filename) - 11, "default.cfg"); + size_t filenameLen = strlen(filename); + qboolean isdefaultcfg = + !strcmp(filename, "default.cfg") || + (filenameLen >= 12 && !strcmp(filename + filenameLen - 12, "/default.cfg")); if (!strcmp(filename, "config.cfg")) { @@ -487,23 +497,204 @@ static void Cmd_Exec(const char *filename) // 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"); + 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. - if (gamemode == GAME_HIPNOTIC) - Cbuf_InsertText("\nsv_gameplayfix_blowupfallenzombies 0\nsys_ticrate 0.02\nsv_gameplayfix_slidemoveprojectiles 0\n\n"); + 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 - 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"); + 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 - if (gamemode == GAME_STEELSTORM) - Cbuf_InsertText("\ncl_csqc_generatemousemoveevents 0\n\n"); + 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; + } } } @@ -785,7 +976,7 @@ static const char *Cmd_GetDirectCvarValue(const char *varname, cmdalias_t *alias cvar_t *cvar; long argno; char *endptr; - char vabuf[1024]; + static char vabuf[1024]; // cmd_mutex if(is_multiple) *is_multiple = false; @@ -910,9 +1101,11 @@ static const char *Cmd_GetCvarValue(const char *var, size_t varlen, cmdalias_t * { static char varname[MAX_INPUTLINE]; // cmd_mutex static char varval[MAX_INPUTLINE]; // cmd_mutex - const char *varstr; + const char *varstr = NULL; char *varfunc; -static char asis[] = "asis"; // just to suppress const char warnings + qboolean required = false; + qboolean optional = false; + static char asis[] = "asis"; // just to suppress const char warnings if(varlen >= MAX_INPUTLINE) varlen = MAX_INPUTLINE - 1; @@ -929,10 +1122,37 @@ static char asis[] = "asis"; // just to suppress const char warnings if(*var == 0) { // empty cvar name? - return NULL; + if(alias) + Con_Printf("Warning: Could not expand $ in alias %s\n", alias->name); + else + Con_Printf("Warning: Could not expand $\n"); + return "$"; } - varstr = NULL; + 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); @@ -948,11 +1168,27 @@ static char asis[] = "asis"; // just to suppress const char warnings if(!varstr) { - if(alias) - Con_Printf("Warning: Could not expand $%s in alias %s\n", varname, alias->name); + 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 - Con_Printf("Warning: Could not expand $%s\n", varname); - return NULL; + { + 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! @@ -977,7 +1213,7 @@ Cmd_PreprocessString Preprocesses strings and replaces $*, $param#, $cvar accordingly. Also strips comments. */ -static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias ) { +static qboolean Cmd_PreprocessString( const char *intext, char *outtext, unsigned maxoutlen, cmdalias_t *alias ) { const char *in; size_t eat, varlen; unsigned outlen; @@ -985,7 +1221,7 @@ static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned ma // don't crash if there's no room in the outtext buffer if( maxoutlen == 0 ) { - return; + return false; } maxoutlen--; // because of \0 @@ -1006,6 +1242,10 @@ static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned ma // 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 @@ -1016,6 +1256,7 @@ static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned ma // 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 @@ -1052,6 +1293,8 @@ static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned ma if(in[varlen + 1] == '}') { val = Cmd_GetCvarValue(in + 1, varlen, alias); + if(!val) + return false; eat = varlen + 2; } else @@ -1063,6 +1306,8 @@ static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned ma } else { varlen = strspn(in, "#*0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"); val = Cmd_GetCvarValue(in, varlen, alias); + if(!val) + return false; eat = varlen; } if(val) @@ -1087,6 +1332,7 @@ static void Cmd_PreprocessString( const char *intext, char *outtext, unsigned ma outtext[outlen++] = *in++; } outtext[outlen] = 0; + return true; } /* @@ -1100,7 +1346,9 @@ static void Cmd_ExecuteAlias (cmdalias_t *alias) { static char buffer[ MAX_INPUTLINE ]; // cmd_mutex static char buffer2[ MAX_INPUTLINE ]; // cmd_mutex - Cmd_PreprocessString( alias->value, buffer, sizeof(buffer) - 2, alias ); + 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) @@ -1132,15 +1380,15 @@ static void Cmd_List_f (void) { partial = Cmd_Argv (1); len = strlen(partial); + ispattern = (strchr(partial, '*') || strchr(partial, '?')); } else { partial = NULL; len = 0; + ispattern = false; } - ispattern = partial && (strchr(partial, '*') || strchr(partial, '?')); - count = 0; for (cmd = cmd_functions; cmd; cmd = cmd->next) { @@ -1664,7 +1912,8 @@ void Cmd_ExecuteString (const char *text, cmd_source_t src, qboolean lockmutex) int found; cmd_function_t *cmd; cmdalias_t *a; - + if (lockmutex) + Cbuf_LockThreadMutex(); oldpos = cmd_tokenizebufferpos; cmd_source = src; found = false; @@ -1740,6 +1989,8 @@ command_found: done: cmd_tokenizebufferpos = oldpos; + if (lockmutex) + Cbuf_UnlockThreadMutex(); } @@ -1857,7 +2108,7 @@ void Cmd_ForwardStringToServer (const char *s) break; } // write the resulting text - SZ_Write(&cls.netcon->message, (unsigned char *)temp, strlen(temp)); + SZ_Write(&cls.netcon->message, (unsigned char *)temp, (int)strlen(temp)); s += 2; continue; }