X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;ds=inline;f=cmd.c;h=4f13c0a9f578bcdb7f92623cbba3e3d136ad892d;hb=3992b4bad986288595baac9b9ea48b76f7cc2dbb;hp=401e44c67300f47805868c5616b61763c543c1e0;hpb=c38d0d2d6409d9b3174b6cf04f1bd09694cbfc81;p=xonotic%2Fdarkplaces.git diff --git a/cmd.c b/cmd.c index 401e44c6..4f13c0a9 100644 --- a/cmd.c +++ b/cmd.c @@ -27,6 +27,9 @@ cmd_state_t cmd_clientfromserver; cmd_state_t cmd_server; cmd_state_t cmd_serverfromclient; +cmd_userdefined_t cmd_userdefined_all; +cmd_userdefined_t cmd_userdefined_null; + typedef struct cmd_iter_s { cmd_state_t *cmd; } @@ -193,7 +196,7 @@ void Cbuf_AddText (cmd_state_t *cmd, const char *text) l = (int)strlen(text); Cbuf_Lock(cmd); - if (cmd->text.cursize + l >= (size_t)cmd->text.maxsize) + if (cmd->text.maxsize - cmd->text.cursize <= l) Con_Print("Cbuf_AddText: overflow\n"); else SZ_Write(&cmd->text, (const unsigned char *)text, l); @@ -234,14 +237,13 @@ Cbuf_Execute_Deferred --blub */ static void Cbuf_Execute_Deferred (cmd_state_t *cmd) { - static double oldrealtime = 0; cmddeferred_t *defcmd, *prev; double eat; - if (realtime - oldrealtime < 0 || realtime - oldrealtime > 1800) oldrealtime = realtime; - eat = realtime - oldrealtime; + if (realtime - cmd->deferred_oldrealtime < 0 || realtime - cmd->deferred_oldrealtime > 1800) cmd->deferred_oldrealtime = realtime; + eat = realtime - cmd->deferred_oldrealtime; if (eat < (1.0 / 120.0)) return; - oldrealtime = realtime; + cmd->deferred_oldrealtime = realtime; prev = NULL; defcmd = cmd->deferred_list; while(defcmd) @@ -325,7 +327,7 @@ void Cbuf_Execute (cmd_state_t *cmd) // 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"); + Con_Warnf("Warning: console input buffer had an overlong line. Ignored.\n"); line[0] = 0; } else @@ -522,6 +524,7 @@ static void Cmd_Exec(cmd_state_t *cmd, const char *filename) "sys_ticrate 0.01388889\n" "r_shadow_gloss 1\n" "r_shadow_bumpscale_basetexture 0\n" +"csqc_polygons_defaultmaterial_nocullface 0\n" ); break; case GAME_NEHAHRA: @@ -546,6 +549,7 @@ static void Cmd_Exec(cmd_state_t *cmd, const char *filename) "sys_ticrate 0.01388889\n" "r_shadow_gloss 1\n" "r_shadow_bumpscale_basetexture 0\n" +"csqc_polygons_defaultmaterial_nocullface 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. @@ -574,6 +578,7 @@ static void Cmd_Exec(cmd_state_t *cmd, const char *filename) "sys_ticrate 0.02\n" "r_shadow_gloss 1\n" "r_shadow_bumpscale_basetexture 0\n" +"csqc_polygons_defaultmaterial_nocullface 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 @@ -599,6 +604,7 @@ static void Cmd_Exec(cmd_state_t *cmd, const char *filename) "sys_ticrate 0.01388889\n" "r_shadow_gloss 1\n" "r_shadow_bumpscale_basetexture 0\n" +"csqc_polygons_defaultmaterial_nocullface 0\n" ); break; case GAME_TENEBRAE: @@ -623,6 +629,7 @@ static void Cmd_Exec(cmd_state_t *cmd, const char *filename) "sys_ticrate 0.01388889\n" "r_shadow_gloss 2\n" "r_shadow_bumpscale_basetexture 4\n" +"csqc_polygons_defaultmaterial_nocullface 0\n" ); break; case GAME_NEXUIZ: @@ -647,6 +654,14 @@ static void Cmd_Exec(cmd_state_t *cmd, const char *filename) "sys_ticrate 0.01388889\n" "sv_gameplayfix_q2airaccelerate 1\n" "sv_gameplayfix_stepmultipletimes 1\n" +"csqc_polygons_defaultmaterial_nocullface 1\n" + ); + break; + case GAME_XONOTIC: + case GAME_VORETOURNAMENT: + // compatibility for versions prior to 2020-05-25, this can be overridden in newer versions to get the default behavior and be consistent with FTEQW engine + Cbuf_InsertText(cmd, "\n" +"csqc_polygons_defaultmaterial_nocullface 1\n" ); break; // Steel Storm: Burning Retribution csqc misinterprets CSQC_InputEvent if type is a value other than 0 or 1 @@ -671,6 +686,7 @@ static void Cmd_Exec(cmd_state_t *cmd, const char *filename) "sv_gameplayfix_downtracesupportsongroundflag 1\n" "sys_ticrate 0.01388889\n" "cl_csqc_generatemousemoveevents 0\n" +"csqc_polygons_defaultmaterial_nocullface 1\n" ); break; default: @@ -693,6 +709,7 @@ static void Cmd_Exec(cmd_state_t *cmd, const char *filename) "sv_gameplayfix_swiminbmodels 1\n" "sv_gameplayfix_downtracesupportsongroundflag 1\n" "sys_ticrate 0.01388889\n" +"csqc_polygons_defaultmaterial_nocullface 0\n" ); break; } @@ -765,7 +782,7 @@ static void Cmd_Toggle_f(cmd_state_t *cmd) else { // Correct Arguments Specified // Acquire Potential CVar - cvar_t* cvCVar = Cvar_FindVar( Cmd_Argv(cmd, 1) ); + cvar_t* cvCVar = Cvar_FindVar(cmd->cvars, Cmd_Argv(cmd, 1), cmd->cvars_flagsmask); if(cvCVar != NULL) { // Valid CVar @@ -843,7 +860,7 @@ static void Cmd_Alias_f (cmd_state_t *cmd) if (Cmd_Argc(cmd) == 1) { Con_Print("Current alias commands:\n"); - for (a = cmd->alias ; a ; a=a->next) + for (a = cmd->userdefined->alias ; a ; a=a->next) Con_Printf("%s : %s", a->name, a->value); return; } @@ -856,7 +873,7 @@ static void Cmd_Alias_f (cmd_state_t *cmd) } // if the alias already exists, reuse it - for (a = cmd->alias ; a ; a=a->next) + for (a = cmd->userdefined->alias ; a ; a=a->next) { if (!strcmp(s, a->name)) { @@ -872,12 +889,12 @@ static void Cmd_Alias_f (cmd_state_t *cmd) 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 ) + for( prev = NULL, current = cmd->userdefined->alias ; current && strcmp( current->name, a->name ) < 0 ; prev = current, current = current->next ) ; if( prev ) { prev->next = a; } else { - cmd->alias = a; + cmd->userdefined->alias = a; } a->next = current; } @@ -924,14 +941,14 @@ static void Cmd_UnAlias_f (cmd_state_t *cmd) { s = Cmd_Argv(cmd, i); p = NULL; - for(a = cmd->alias; a; p = a, a = a->next) + for(a = cmd->userdefined->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(a == cmd->userdefined->alias) + cmd->userdefined->alias = a->next; if(p) p->next = a->next; Z_Free(a->value); @@ -1013,7 +1030,7 @@ static const char *Cmd_GetDirectCvarValue(cmd_state_t *cmd, const char *varname, } } - if((cvar = Cvar_FindVar(varname)) && !(cvar->flags & CVAR_PRIVATE)) + if((cvar = Cvar_FindVar(cmd->cvars, varname, cmd->cvars_flagsmask)) && !(cvar->flags & CVAR_PRIVATE)) return cvar->string; return NULL; @@ -1104,9 +1121,9 @@ static const char *Cmd_GetCvarValue(cmd_state_t *cmd, const char *var, size_t va { // empty cvar name? if(alias) - Con_Printf("Warning: Could not expand $ in alias %s\n", alias->name); + Con_Warnf("Warning: Could not expand $ in alias %s\n", alias->name); else - Con_Printf("Warning: Could not expand $\n"); + Con_Warnf("Warning: Could not expand $\n"); return "$"; } @@ -1152,9 +1169,9 @@ static const char *Cmd_GetCvarValue(cmd_state_t *cmd, const char *var, size_t va if(required) { if(alias) - Con_Printf("Error: Could not expand $%s in alias %s\n", varname, alias->name); + Con_Errorf("Error: Could not expand $%s in alias %s\n", varname, alias->name); else - Con_Printf("Error: Could not expand $%s\n", varname); + Con_Errorf("Error: Could not expand $%s\n", varname); return NULL; } else if(optional) @@ -1164,9 +1181,9 @@ static const char *Cmd_GetCvarValue(cmd_state_t *cmd, const char *var, size_t va else { if(alias) - Con_Printf("Warning: Could not expand $%s in alias %s\n", varname, alias->name); + Con_Warnf("Warning: Could not expand $%s in alias %s\n", varname, alias->name); else - Con_Printf("Warning: Could not expand $%s\n", varname); + Con_Warnf("Warning: Could not expand $%s\n", varname); dpsnprintf(varval, sizeof(varval), "$%s", varname); return varval; } @@ -1371,7 +1388,14 @@ static void Cmd_List_f (cmd_state_t *cmd) } count = 0; - for (func = cmd->functions; func; func = func->next) + for (func = cmd->userdefined->csqc_functions; func; func = func->next) + { + if (partial && (ispattern ? !matchpattern_with_separator(func->name, partial, false, "", false) : strncmp(partial, func->name, len))) + continue; + Con_Printf("%s : %s\n", func->name, func->description); + count++; + } + for (func = cmd->engine_functions; func; func = func->next) { if (partial && (ispattern ? !matchpattern_with_separator(func->name, partial, false, "", false) : strncmp(partial, func->name, len))) continue; @@ -1413,15 +1437,24 @@ static void Cmd_Apropos_f(cmd_state_t *cmd) partial = va(vabuf, sizeof(vabuf), "*%s*", partial); count = 0; - for (cvar = cvar_vars; cvar; cvar = cvar->next) + for (cvar = cmd->cvars->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); + Con_Printf ("cvar "); + Cvar_PrintHelp(cvar, true); count++; } - for (func = cmd->functions; func; func = func->next) + for (func = cmd->userdefined->csqc_functions; func; func = func->next) + { + if (!matchpattern_with_separator(func->name, partial, true, "", false)) + if (!matchpattern_with_separator(func->description, partial, true, "", false)) + continue; + Con_Printf("command ^2%s^7: %s\n", func->name, func->description); + count++; + } + for (func = cmd->engine_functions; func; func = func->next) { if (!matchpattern_with_separator(func->name, partial, true, "", false)) if (!matchpattern_with_separator(func->description, partial, true, "", false)) @@ -1429,7 +1462,7 @@ static void Cmd_Apropos_f(cmd_state_t *cmd) Con_Printf("command ^2%s^7: %s\n", func->name, func->description); count++; } - for (alias = cmd->alias; alias; alias = alias->next) + for (alias = cmd->userdefined->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)) @@ -1459,6 +1492,22 @@ void Cmd_Init(void) cmd->text.cursize = 0; cmd->null_string = ""; } + // client console can see server cvars because the user may start a server + cmd_client.cvars = &cvars_all; + cmd_client.cvars_flagsmask = CVAR_CLIENT | CVAR_SERVER; + cmd_client.userdefined = &cmd_userdefined_all; + // stuffcmd from server has access to the reasonable client things, but it probably doesn't need to access the client's server-only cvars + cmd_clientfromserver.cvars = &cvars_all; + cmd_clientfromserver.cvars_flagsmask = CVAR_CLIENT; + cmd_clientfromserver.userdefined = &cmd_userdefined_all; + // dedicated server console can only see server cvars, there is no client + cmd_server.cvars = &cvars_all; + cmd_server.cvars_flagsmask = CVAR_SERVER; + cmd_server.userdefined = &cmd_userdefined_all; + // server commands received from clients have no reason to access cvars, cvar expansion seems perilous. + cmd_serverfromclient.cvars = &cvars_null; + cmd_serverfromclient.cvars_flagsmask = 0; + cmd_serverfromclient.userdefined = &cmd_userdefined_null; } void Cmd_Init_Commands(qboolean dedicated_server) @@ -1468,6 +1517,7 @@ void Cmd_Init_Commands(qboolean dedicated_server) // // client-only commands Cmd_AddCommand(&cmd_client, "cmd", Cmd_ForwardToServer_f, "send a console commandline to the server (used by some mods)"); + Cmd_AddCommand(&cmd_clientfromserver, "cmd", Cmd_ForwardToServer_f, "send a console commandline to the server (used by some mods)"); Cmd_AddCommand(&cmd_client, "wait", Cmd_Wait_f, "make script execution wait for next rendered frame"); Cmd_AddCommand(&cmd_client, "cprint", Cmd_Centerprint_f, "print something at the screen center"); @@ -1656,43 +1706,69 @@ void Cmd_AddCommand(cmd_state_t *cmd, const char *cmd_name, xcommand_t function, cmd_function_t *prev, *current; // fail if the command is a variable name - if (Cvar_FindVar( cmd_name )) + if (Cvar_FindVar(cmd->cvars, cmd_name, ~0)) { Con_Printf("Cmd_AddCommand: %s already defined as a var\n", cmd_name); return; } - // fail if the command already exists in this interpreter - for (func = cmd->functions; func; func = func->next) - if (!strcmp(cmd_name, func->name)) - break; - - if (func) + if (function) { - // command already defined... - if (function) - Con_Printf("Cmd_AddCommand: %s already defined\n", cmd_name); - else //[515]: csqc - func->csqcfunc = true; + // fail if the command already exists in this interpreter + for (func = cmd->engine_functions; func; func = func->next) + { + if (!strcmp(cmd_name, func->name)) + { + Con_Printf("Cmd_AddCommand: %s already defined\n", cmd_name); + return; + } + } + + func = (cmd_function_t *)Mem_Alloc(cmd->mempool, sizeof(cmd_function_t)); + func->name = cmd_name; + func->function = function; + func->description = description; + func->next = cmd->engine_functions; + + // insert it at the right alphanumeric position + for (prev = NULL, current = cmd->engine_functions; current && strcmp(current->name, func->name) < 0; prev = current, current = current->next) + ; + if (prev) { + prev->next = func; + } + else { + cmd->engine_functions = func; + } + func->next = current; } else { + // mark csqcfunc if the function already exists in the csqc_functions list + for (func = cmd->userdefined->csqc_functions; func; func = func->next) + { + if (!strcmp(cmd_name, func->name)) + { + func->csqcfunc = true; //[515]: csqc + return; + } + } + + func = (cmd_function_t *)Mem_Alloc(cmd->mempool, sizeof(cmd_function_t)); func->name = cmd_name; func->function = function; func->description = description; - if (!function) //[515]: csqc - func->csqcfunc = true; - func->next = cmd->functions; + func->csqcfunc = true; //[515]: csqc + func->next = cmd->userdefined->csqc_functions; // insert it at the right alphanumeric position - for (prev = NULL, current = cmd->functions; current && strcmp(current->name, func->name) < 0; prev = current, current = current->next) + for (prev = NULL, current = cmd->userdefined->csqc_functions; current && strcmp(current->name, func->name) < 0; prev = current, current = current->next) ; if (prev) { prev->next = func; } else { - cmd->functions = func; + cmd->userdefined->csqc_functions = func; } func->next = current; } @@ -1707,7 +1783,11 @@ qboolean Cmd_Exists (cmd_state_t *cmd, const char *cmd_name) { cmd_function_t *func; - for (func=cmd->functions ; func ; func=func->next) + for (func = cmd->userdefined->csqc_functions; func; func = func->next) + if (!strcmp(cmd_name, func->name)) + return true; + + for (func=cmd->engine_functions ; func ; func=func->next) if (!strcmp (cmd_name,func->name)) return true; @@ -1731,7 +1811,11 @@ const char *Cmd_CompleteCommand (cmd_state_t *cmd, const char *partial) return NULL; // check functions - for (func = cmd->functions; func; func = func->next) + for (func = cmd->userdefined->csqc_functions; func; func = func->next) + if (!strncasecmp(partial, func->name, len)) + return func->name; + + for (func = cmd->engine_functions; func; func = func->next) if (!strncasecmp(partial, func->name, len)) return func->name; @@ -1760,7 +1844,11 @@ int Cmd_CompleteCountPossible (cmd_state_t *cmd, const char *partial) return 0; // Loop through the command list and count all partial matches - for (func = cmd->functions; func; func = func->next) + for (func = cmd->userdefined->csqc_functions; func; func = func->next) + if (!strncasecmp(partial, func->name, len)) + h++; + + for (func = cmd->engine_functions; func; func = func->next) if (!strncasecmp(partial, func->name, len)) h++; @@ -1786,8 +1874,11 @@ const char **Cmd_CompleteBuildList (cmd_state_t *cmd, const char *partial) len = strlen(partial); buf = (const char **)Mem_Alloc(tempmempool, sizeofbuf + sizeof (const char *)); - // Loop through the alias list and print all matches - for (func = cmd->functions; func; func = func->next) + // Loop through the functions lists and print all matches + for (func = cmd->userdefined->csqc_functions; func; func = func->next) + if (!strncasecmp(partial, func->name, len)) + buf[bpos++] = func->name; + for (func = cmd->engine_functions; func; func = func->next) if (!strncasecmp(partial, func->name, len)) buf[bpos++] = func->name; @@ -1801,7 +1892,10 @@ void Cmd_CompleteCommandPrint (cmd_state_t *cmd, const char *partial) cmd_function_t *func; size_t len = strlen(partial); // Loop through the command list and print all matches - for (func = cmd->functions; func; func = func->next) + for (func = cmd->userdefined->csqc_functions; func; func = func->next) + if (!strncasecmp(partial, func->name, len)) + Con_Printf("^2%s^7: %s\n", func->name, func->description); + for (func = cmd->engine_functions; func; func = func->next) if (!strncasecmp(partial, func->name, len)) Con_Printf("^2%s^7: %s\n", func->name, func->description); } @@ -1826,7 +1920,7 @@ const char *Cmd_CompleteAlias (cmd_state_t *cmd, const char *partial) return NULL; // Check functions - for (alias = cmd->alias; alias; alias = alias->next) + for (alias = cmd->userdefined->alias; alias; alias = alias->next) if (!strncasecmp(partial, alias->name, len)) return alias->name; @@ -1839,7 +1933,7 @@ void Cmd_CompleteAliasPrint (cmd_state_t *cmd, 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) + for (alias = cmd->userdefined->alias; alias; alias = alias->next) if (!strncasecmp(partial, alias->name, len)) Con_Printf("^5%s^7: %s", alias->name, alias->value); } @@ -1868,7 +1962,7 @@ int Cmd_CompleteAliasCountPossible (cmd_state_t *cmd, const char *partial) return 0; // Loop through the command list and count all partial matches - for (alias = cmd->alias; alias; alias = alias->next) + for (alias = cmd->userdefined->alias; alias; alias = alias->next) if (!strncasecmp(partial, alias->name, len)) h++; @@ -1895,7 +1989,7 @@ const char **Cmd_CompleteAliasBuildList (cmd_state_t *cmd, const char *partial) 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) + for (alias = cmd->userdefined->alias; alias; alias = alias->next) if (!strncasecmp(partial, alias->name, len)) buf[bpos++] = alias->name; @@ -1903,11 +1997,18 @@ const char **Cmd_CompleteAliasBuildList (cmd_state_t *cmd, const char *partial) return buf; } -void Cmd_ClearCsqcFuncs (cmd_state_t *cmd) +// TODO: Make this more generic? +void Cmd_ClearCSQCCommands (cmd_state_t *cmd) { cmd_function_t *func; - for (func = cmd->functions; func; func = func->next) - func->csqcfunc = false; + cmd_function_t **next = &cmd->userdefined->csqc_functions; + + while(*next) + { + func = *next; + *next = func->next; + Z_Free(func); + } } /* @@ -1918,6 +2019,8 @@ A complete command line has been parsed, so try to execute it FIXME: lookupnoadd the token to speed search? ============ */ +extern hook_t *csqc_concmd; + void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qboolean lockmutex) { int oldpos; @@ -1935,12 +2038,20 @@ void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qb goto done; // no tokens // check functions - for (func = cmd->functions; func; func=func->next) + for (func = cmd->userdefined->csqc_functions; func; func = func->next) { - if (!strcasecmp (cmd->argv[0], func->name)) + if (!strcasecmp(cmd->argv[0], func->name)) { - if (func->csqcfunc && CL_VM_ConsoleCommand (text)) //[515]: csqc + if (func->csqcfunc && Hook_Call(csqc_concmd, text)->bval) //[515]: csqc goto done; + break; + } + } + + for (func = cmd->engine_functions; func; func=func->next) + { + if (!strcasecmp (cmd->argv[0], func->name)) + { switch (src) { case src_command: @@ -1963,12 +2074,12 @@ void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qb // if it's a client command and no command was found, say so. if (cmd->source == src_client) { - Con_Printf("player \"%s\" tried to %s\n", host_client->name, text); + Con_Printf("Client \"%s\" tried to execute \"%s\"\n", host_client->name, text); goto done; } // check alias - for (a=cmd->alias ; a ; a=a->next) + for (a=cmd->userdefined->alias ; a ; a=a->next) { if (!strcasecmp (cmd->argv[0], a->name)) { @@ -1978,9 +2089,13 @@ void Cmd_ExecuteString (cmd_state_t *cmd, const char *text, cmd_source_t src, qb } // check cvars - if (!Cvar_Command (cmd) && host_framecount > 0) - Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(cmd, 0)); - + if (!Cvar_Command(cmd) && host_framecount > 0) { + if (cmd == &cmd_clientfromserver) { + Con_Printf("Server tried to execute \"%s\"\n", Cmd_Argv(cmd, 0)); + } else { + Con_Printf("Unknown command \"%s\"\n", Cmd_Argv(cmd, 0)); + } + } done: cmd->tokenizebufferpos = oldpos; if (lockmutex) @@ -2179,15 +2294,17 @@ void Cmd_SaveInitState(void) cmd_state_t *cmd = cmd_iter->cmd; cmd_function_t *f; cmdalias_t *a; - for (f = cmd->functions; f; f = f->next) + for (f = cmd->userdefined->csqc_functions; f; f = f->next) f->initstate = true; - for (a = cmd->alias; a; a = a->next) + for (f = cmd->engine_functions; f; f = f->next) + f->initstate = true; + for (a = cmd->userdefined->alias; a; a = a->next) { a->initstate = true; a->initialvalue = Mem_strdup(zonemempool, a->value); } } - Cvar_SaveInitState(); + Cvar_SaveInitState(&cvars_all); } void Cmd_RestoreInitState(void) @@ -2198,7 +2315,19 @@ void Cmd_RestoreInitState(void) cmd_state_t *cmd = cmd_iter->cmd; cmd_function_t *f, **fp; cmdalias_t *a, **ap; - for (fp = &cmd->functions; (f = *fp);) + for (fp = &cmd->userdefined->csqc_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 (fp = &cmd->engine_functions; (f = *fp);) { if (f->initstate) fp = &f->next; @@ -2210,7 +2339,7 @@ void Cmd_RestoreInitState(void) Z_Free(f); } } - for (ap = &cmd->alias; (a = *ap);) + for (ap = &cmd->userdefined->alias; (a = *ap);) { if (a->initstate) { @@ -2235,5 +2364,5 @@ void Cmd_RestoreInitState(void) } } } - Cvar_RestoreInitState(); + Cvar_RestoreInitState(&cvars_all); }