]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Improve sv_spectate 0 notifications and description, refactor nospectators command
authorbones_was_here <bones_was_here@xonotic.au>
Sat, 13 Jul 2024 15:04:57 +0000 (01:04 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Mon, 5 Aug 2024 16:26:28 +0000 (02:26 +1000)
The blockSpectators global is redundant.
See https://gitlab.com/xonotic/xonotic-data.pk3dir/-/merge_requests/1289

Players are now given the grace period and SPECTATE_WARNING when
sv_spectate is disabled during a game, as well as when `nospectators` is
voted.

Centreprints are added and displayed when they don't conflict with join
restriction centreprints.

notifications.cfg
qcsrc/common/notifications/all.inc
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/clientkill.qc
qcsrc/server/command/cmd.qc
qcsrc/server/command/sv_cmd.qc
xonotic-server.cfg

index bc2693c21545253aaa91e6d302f424f457faf3e2..c6f47737b8fcb551c477539e955b0cef9803e0c1 100644 (file)
@@ -555,6 +555,8 @@ seta notification_CENTER_ROUND_TIED "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_SEQUENCE_COMPLETED "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_SEQUENCE_COUNTER "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_SEQUENCE_COUNTER_FEWMORE "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_SPECTATE_NOTALLOWED "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_SPECTATE_WARNING "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_SUPERWEAPON_BROKEN "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_SUPERWEAPON_LOST "1" "0 = off, 1 = centerprint"
 seta notification_CENTER_SUPERWEAPON_PICKUP "1" "0 = off, 1 = centerprint"
index 60a9e24498c4a4ebad69531b2b1d999bf04efd07..048310a72a557fb91ef1c119095cf3fa8c3ee588 100644 (file)
@@ -801,6 +801,9 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input !=
     MSG_CENTER_NOTIF(SEQUENCE_COUNTER,                  N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  _("^BGThere are more to go..."), "")
     MSG_CENTER_NOTIF(SEQUENCE_COUNTER_FEWMORE,          N_ENABLE,    0, 1, "f1",             CPID_Null,              "0 0",  _("^BGOnly %s^BG more to go..."), "")
 
+    MSG_CENTER_NOTIF(SPECTATE_WARNING,                  N_ENABLE,    0, 1, "f1secs",         CPID_PREVENT_JOIN,      "0 0",  _("^F2You have to become a player within the next %s, otherwise you will be kicked, because spectating isn't allowed at this time!"), "") // same string as INFO_SPECTATE_WARNING
+    MSG_CENTER_NOTIF(SPECTATE_NOTALLOWED,               N_ENABLE,    0, 0, "",               CPID_Null,              "0 0",  _("^F2Spectating isn't allowed at this time!"), "")
+
     MSG_CENTER_NOTIF(SUPERWEAPON_BROKEN,                N_ENABLE,    0, 0, "",               CPID_POWERUP,           "0 0",  _("^F2Superweapons have broken down"), "")
     MSG_CENTER_NOTIF(SUPERWEAPON_LOST,                  N_ENABLE,    0, 0, "",               CPID_POWERUP,           "0 0",  _("^F2Superweapons have been lost"), "")
     MSG_CENTER_NOTIF(SUPERWEAPON_PICKUP,                N_ENABLE,    0, 0, "",               CPID_POWERUP,           "0 0",  _("^F2You now have a superweapon"), "")
index b259481422a222cc25071766c3827257aa1ca23a..d3ca5508f52c19c6b9ad4d9b43faf490a7c3b8e4 100644 (file)
@@ -1171,10 +1171,9 @@ void ClientConnect(entity this)
        bot_relinkplayerlist();
 
        CS(this).spectatortime = time;
-       if (blockSpectators)
-       {
+       if (!autocvar_sv_spectate)
+               // no centreprint here: player forced to join, or informed of why they can't via centreprint
                Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
-       }
 
        CS(this).jointime = time;
 
@@ -2785,14 +2784,20 @@ void PlayerFrame (entity this)
        anticheat_prethink(this);
 
        // Check if spectating is allowed
-       if (!autocvar_sv_spectate) blockSpectators = 1;
-
-       if (blockSpectators && IS_REAL_CLIENT(this)
-       && (IS_SPEC(this) || IS_OBSERVER(this)) && !INGAME(this)
-       && time > (CS(this).spectatortime + autocvar_g_maxplayers_spectator_blocktime))
+       if (!autocvar_sv_spectate && IS_REAL_CLIENT(this)
+       && (IS_SPEC(this) || IS_OBSERVER(this)) && !INGAME(this))
        {
-               if (dropclient_schedule(this))
-                       Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_QUIT_KICK_SPECTATING);
+               float cutoff = CS(this).spectatortime + autocvar_g_maxplayers_spectator_blocktime;
+               if (time > cutoff + MIN_SPEC_TIME * 0.5)
+               {
+                       // sv_spectate was disabled recently (or the server was stalled far too long)
+                       CS(this).spectatortime = time; // reset the grace period
+                       Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
+                       Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
+               }
+               else if (time > cutoff)
+                       if (dropclient_schedule(this))
+                               Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_QUIT_KICK_SPECTATING);
        }
 
        // Check for nameless players
index 890a223a02f09eec53e77fc49f8df6c29e2422ee..d7fb948373ab1c45e692deb63f518cc1d2ca2e63 100644 (file)
@@ -54,7 +54,7 @@ int autocvar_sv_name_maxlength = 64;
 string autocvar_sv_quickmenu_file;
 bool autocvar_sv_servermodelsonly;
 bool autocvar_sv_showspectators;
-int autocvar_sv_spectate;
+bool autocvar_sv_spectate;
 bool autocvar_sv_teamnagger;
 float autocvar_sv_player_scale;
 
@@ -333,7 +333,6 @@ const int RESPAWN_FORCE = BIT(0);
 const int RESPAWN_SILENT = BIT(1);
 const int RESPAWN_DENY = BIT(2);
 
-float blockSpectators; // if set, new or existing spectators or observers will be removed unless they become a player within g_maxplayers_spectator_blocktime seconds
 .float spectatortime; // point in time since the client is spectating or observing
 
 .bool player_blocked;
index d692d8723eec12feadcc5fbc9c8c14bb9b51bf28..293f423084031d731d603d9ca45ae378e760928d 100644 (file)
@@ -32,7 +32,8 @@ void ClientKill_Now_TeamChange(entity this)
        }
        else if (this.killindicator_teamchange == -2)
        {
-               if (blockSpectators)
+               if (!autocvar_sv_spectate)
+                       // shouldn't get here because of condition in ClientCommand_spectate()
                        Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
 
                if (this.wants_join)
index aaf1c11065025d6a4ccddb8bc205eff2e7e5fb00..1a45053b6d88a291887ec8567b8edc6c30659f36 100644 (file)
@@ -694,8 +694,10 @@ void ClientCommand_spectate(entity caller, int request)
                                if (mutator_returnvalue == MUT_SPECCMD_RETURN) return;
 
                                if ((IS_PLAYER(caller) || mutator_returnvalue == MUT_SPECCMD_FORCE || caller.wants_join))
-                               if (autocvar_sv_spectate == 1)
+                               if (autocvar_sv_spectate)
                                        ClientKill_TeamChange(caller, -2); // observe
+                               else
+                                       Send_Notification(NOTIF_ONE_ONLY, caller, MSG_CENTER, CENTER_SPECTATE_NOTALLOWED);
                        }
                        return; // never fall through to usage
                }
index 23c0df96fe8ca38b1db1dc85d131bbf079d6ff71..475f7eb5a9381c3e2d00c2035085a60e16f7c7a5 100644 (file)
@@ -1180,13 +1180,8 @@ void GameCommand_nospectators(int request)
                                LOG_HELPF("This command works only when the server is running.");
                                return;
                        }
-                       blockSpectators = 1;
-                       // give every spectator <g_maxplayers_spectator_blocktime> seconds time to become a player
-                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && (IS_SPEC(it) || IS_OBSERVER(it)) && !INGAME(it), {
-                               CS(it).spectatortime = time;
-                               Send_Notification(NOTIF_ONE_ONLY, it, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
-                       });
-                       bprint(strcat("^7All spectators will be automatically kicked when not joining the game after ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds!\n"));
+                       cvar_settemp("sv_spectate", "0");
+                       // if sv_spectate was enabled PlayerFrame() sends SPECTATE_WARNING notifications
                        return;
                }
 
@@ -1195,6 +1190,7 @@ void GameCommand_nospectators(int request)
                {
                        LOG_HELP("Usage:^3 sv_cmd nospectators");
                        LOG_HELP("  No arguments required.");
+                       LOG_HELP("Temporarily disables the ^3sv_spectate ^7cvar.");
                        return;
                }
        }
index f160255dee5fedce2a77a94a7d42d88e23e3c839..327abe3f30fd353f8b53c1ced19de26081ca4d72 100644 (file)
@@ -27,7 +27,7 @@ alias sv_hook_readyrestart
 set teamplay_lockonrestart 0 "lock teams once all players readied up and the game restarted (no new players can join after restart unless using the server-command unlockteams)"
 
 set g_maxplayers 0 "maximum number of players allowed to play at the same time, 0 means unlimited, -1 uses the map setting or unlimited if not set (rounded to multiple of team number)"
-set g_maxplayers_spectator_blocktime 5 "if the players voted for the \"nospectators\" command, this setting defines the number of seconds a observer/spectator has time to join the game before they get kicked"
+set g_maxplayers_spectator_blocktime 5 "if sv_spectate is disabled, such as by voting for \"nospectators\", this setting defines the number of seconds an observer/spectator has to join the game before they get kicked"
 
 // tournament mod
 set g_warmup 0 "splits the game into warmup and match stages, 1 means the match starts when g_warmup_majority_factor of players are ready OR g_warmup_limit is hit, >1 also requires at least g_warmup players (including bots) to join, -1 means that minimum player requrement is set by the map (lower bound of 2 or 2 per team)"
@@ -95,7 +95,7 @@ set sv_precacheplayermodels 1 "preload all the player models at game start, to a
 set sv_spectator_speed_multiplier 1.5 "base movement speed factor of spectators, all movement settings scale off this"
 set sv_spectator_speed_multiplier_min 1 "minimum movement speed factor for spectators as determined by scrolling"
 set sv_spectator_speed_multiplier_max 5 "maximum movement speed factor for spectators as determined by scrolling"
-set sv_spectate 1 "if set to 1, new clients are allowed to spectate or observe the game, if set to 0 joining clients spawn as players immediately (no spectating)"
+set sv_spectate 1 "if set to 1 clients are allowed to spectate or observe the game, if set to 0 clients spawn as players immediately or are kicked after g_maxplayers_spectator_blocktime if that's not possible (incompatible with spec-based features such as sv_maxidle_playertospectator and g_balance_teams_queue)"
 set sv_defaultcharacter 0 "master switch, if set to 1 the further configuration for replacing all player models, skins and colors is taken from the sv_defaultplayermodel, sv_defaultplayerskin and sv_defaultplayercolors variables"
 set sv_defaultcharacterskin 0 "if set to 1 the further configuration for replacing all skins is taken from the sv_defaultplayerskin variables"
 set sv_defaultplayermodel "models/player/erebus.iqm" "default model selection, only works if sv_defaultcharacter is set to 1; you may append a :<skinnumber> suffix to model names; you can specify multiple, separated by space, and a random one will be chosen"