]> git.xonotic.org Git - xonotic/darkplaces.git/commitdiff
dedicated server: don't register client-only cvars
authorbones_was_here <bones_was_here@xonotic.au>
Mon, 17 Jul 2023 15:26:12 +0000 (01:26 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Mon, 17 Jul 2023 16:24:20 +0000 (02:24 +1000)
Fixes random client cvars like r_trippy and cl_netpacketloss_send
appearing in the server.

Adds a warn (instead of crashing) for if we try to set an unregistered
engine cvar somewhere.

cmd.h
cvar.c
fs.c
host.c
sv_main.c

diff --git a/cmd.h b/cmd.h
index bee0a1f36b520b0695e863e0cdeda6de942a3e3d..fddd2a08d88b25883264e9c9d6388401fcc59fd0 100644 (file)
--- a/cmd.h
+++ b/cmd.h
@@ -59,8 +59,9 @@ struct cmd_state_s;
 #define CF_PRIVATE              (1<<11) // cvar should not be $ expanded or sent to the server under any circumstances (rcon_password, etc)
 #define CF_MAXFLAGSVAL          ((1<<12) - 1)    // used to determine if flags is valid
 // for internal use only!
+#define CF_REGISTERED (1<<29)  // created by Cvar_RegisterVariable()
 #define CF_DEFAULTSET (1<<30)
-#define CF_ALLOCATED (1<<31)
+#define CF_ALLOCATED (1<<31)   // created by Cvar_Get() (console or QC)
 
 #define CF_SHARED 3
 
diff --git a/cvar.c b/cvar.c
index 7936c92356be359c13748eca7afbec3250df8ac2..98f11e399ba6d924f9487dadf96b266d0e470d27 100644 (file)
--- a/cvar.c
+++ b/cvar.c
@@ -437,6 +437,12 @@ void Cvar_SetQuick (cvar_t *var, const char *value)
                return;
        }
 
+       if (!(var->flags & CF_REGISTERED) && !(var->flags & CF_ALLOCATED))
+       {
+               Con_Printf(CON_WARN "Warning: Cvar_SetQuick() cannot set unregistered cvar \"%s\"\n", var->name);
+               return; // setting an unregistered engine cvar crashes
+       }
+
        if (developer_extra.integer)
                Con_DPrintf("Cvar_SetQuick({\"%s\", \"%s\", %i, \"%s\"}, \"%s\");\n", var->name, var->string, var->flags, var->defstring, value);
 
@@ -498,22 +504,25 @@ void Cvar_RegisterVirtual(cvar_t *variable, const char *name )
        cvar_hash_t *hash;
        int hashindex;
 
+       if (cls.state == ca_dedicated && !(variable->flags & CF_SERVER))
+               return;
+
        if(!*name)
        {
-               Con_Printf("Cvar_RegisterVirtual: invalid virtual cvar name\n");
+               Con_Printf(CON_WARN "Cvar_RegisterVirtual: invalid virtual cvar name\n");
                return;
        }
 
        // check for overlap with a command
        if (Cmd_Exists(cmd_local, name))
        {
-               Con_Printf("Cvar_RegisterVirtual: %s is a command\n", name);
+               Con_Printf(CON_WARN "Cvar_RegisterVirtual: %s is a command\n", name);
                return;
        }
 
        if(Cvar_FindVar(&cvars_all, name, 0))
        {
-               Con_Printf("Cvar_RegisterVirtual: %s is a cvar\n", name);
+               Con_Printf(CON_WARN "Cvar_RegisterVirtual: %s is a cvar\n", name);
                return;
        }
 
@@ -579,7 +588,9 @@ void Cvar_RegisterVariable (cvar_t *variable)
 
        switch (variable->flags & (CF_CLIENT | CF_SERVER))
        {
-       case CF_CLIENT:
+       case CF_CLIENT: // client-only cvar
+               if (cls.state == ca_dedicated)
+                       return;
        case CF_SERVER:
        case CF_CLIENT | CF_SERVER:
                cvars = &cvars_all;
@@ -607,7 +618,7 @@ void Cvar_RegisterVariable (cvar_t *variable)
                        // (because the engine directly accesses fixed variables)
                        // NOTE: this isn't actually used currently
                        // (all cvars are registered before config parsing)
-                       variable->flags |= (cvar->flags & ~CF_ALLOCATED);
+                       variable->flags &= ~CF_ALLOCATED;
                        // cvar->string is now owned by variable instead
                        variable->string = cvar->string;
                        variable->defstring = cvar->defstring;
@@ -662,6 +673,9 @@ void Cvar_RegisterVariable (cvar_t *variable)
        for (i = 0;i < PRVM_PROG_MAX;i++)
                variable->globaldefindex[i] = -1;
 
+       // Safe for Cvar_SetQuick()
+       variable->flags |= CF_REGISTERED;
+
        Cvar_Link(variable, cvars);
 }
 
diff --git a/fs.c b/fs.c
index 25789e0235888c1f58d199fd65c30184e6711e70..56ce8cac0900f2717a55adb7c210f544db4bdd3e 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -1513,13 +1513,16 @@ void FS_Rescan (void)
        // add back the selfpack as new first item
        FS_AddSelfPack();
 
-       // set the default screenshot name to either the mod name or the
-       // gamemode screenshot name
-       if (strcmp(com_modname, gamedirname1))
-               Cvar_SetQuick (&scr_screenshot_name, com_modname);
-       else
-               Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname);
-       
+       if (cls.state != ca_dedicated)
+       {
+               // set the default screenshot name to either the mod name or the
+               // gamemode screenshot name
+               if (strcmp(com_modname, gamedirname1))
+                       Cvar_SetQuick (&scr_screenshot_name, com_modname);
+               else
+                       Cvar_SetQuick (&scr_screenshot_name, gamescreenshotname);
+       }
+
        if((i = Sys_CheckParm("-modname")) && i < sys.argc - 1)
                strlcpy(com_modname, sys.argv[i+1], sizeof(com_modname));
 
diff --git a/host.c b/host.c
index e34f712bebb2e148456af2f1e7afe2a71adb7739..8b64f9df9119ed61d93cce6360b6dc7a6acf52ee 100644 (file)
--- a/host.c
+++ b/host.c
@@ -424,6 +424,10 @@ static void Host_Init (void)
        if (Sys_CheckParm("-nostdout"))
                sys_nostdout = 1;
 
+       // -dedicated is checked in SV_ServerOptions() but that's too late for Cvar_RegisterVariable() to skip all the client-only cvars
+       if (Sys_CheckParm ("-dedicated") || !cl_available)
+               cls.state = ca_dedicated;
+
        // initialize console command/cvar/alias/command execution systems
        Cmd_Init();
 
index 16fd612b9af1fa942b8bec6658ed556ce8daaba7..ac35d949bd16b0b6323bfb13c8d8c0ee34437e5b 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -452,7 +452,6 @@ static void SV_ServerOptions (void)
        i = Sys_CheckParm ("-dedicated");
        if (i || !cl_available)
        {
-               cls.state = ca_dedicated;
                // check for -dedicated specifying how many players
                if (i && i + 1 < sys.argc && atoi (sys.argv[i+1]) >= 1)
                        svs.maxclients = atoi (sys.argv[i+1]);
@@ -2604,7 +2603,8 @@ double SV_Frame(double time)
                {
                        advancetime = sys_ticrate.value;
                        // listen servers can run multiple server frames per client frame
-                       framelimit = cl_maxphysicsframesperserverframe.integer;
+                       if (cl_maxphysicsframesperserverframe.integer > 0)
+                               framelimit = cl_maxphysicsframesperserverframe.integer;
                        aborttime = Sys_DirtyTime() + 0.1;
                }