From be1abb0f9220178ce9d5f1b8de02df8155072ea0 Mon Sep 17 00:00:00 2001 From: greenmarine Date: Sun, 18 May 2008 09:43:40 +0000 Subject: [PATCH] new feature: g_maxplayers (set to 0 to disable) allows to define the number of players allowed to join the game. Has to be smaller or equal to "maxplayers". New server-side command "nospectators" which players can vote for. Will kick all spectators after a defined number of seconds, unless these spectators manage to join the game in time. git-svn-id: svn://svn.icculus.org/nexuiz/trunk@3631 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/default.cfg | 4 ++ data/qcsrc/server/cl_client.qc | 80 ++++++++++++++++++++++++----- data/qcsrc/server/clientcommands.qc | 16 ++++-- data/qcsrc/server/defs.qh | 5 ++ data/qcsrc/server/gamecommand.qc | 15 ++++++ 5 files changed, 102 insertions(+), 18 deletions(-) diff --git a/data/default.cfg b/data/default.cfg index 3c37aebfc..e6b104098 100644 --- a/data/default.cfg +++ b/data/default.cfg @@ -37,6 +37,7 @@ alias -hook -button6 alias ready "cmd ready" alias lockteams "sv_cmd lockteams" alias unlockteams "sv_cmd unlockteams" +alias nospectators "sv_cmd nospectators" alias bsp "ls maps/*.bsp" alias chmap "changelevel $*" @@ -123,6 +124,9 @@ set sv_ready_restart_nag_interval 10 //how long the pause between the ready-nags //nifreks lockonrestart feature, used in team-based game modes, if set to 1 and all players readied up no other player can then join the game anymore, useful to block spectators from joining set teamplay_lockonrestart 0 +set g_maxplayers 0 //maximum number of players allowed to play at the same time, set to 0 to all players to join the game +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 he gets kicked + // use default physics exec physicsQBR.cfg diff --git a/data/qcsrc/server/cl_client.qc b/data/qcsrc/server/cl_client.qc index a84ba6720..6a24ee773 100644 --- a/data/qcsrc/server/cl_client.qc +++ b/data/qcsrc/server/cl_client.qc @@ -353,6 +353,8 @@ void PutObserverInServer (void) else if(self.killcount != -666) bprint ("^4", self.netname, "^4 is spectating now\n"); + self.spectatortime = time; + self.classname = "observer"; self.health = -666; self.takedamage = DAMAGE_NO; @@ -970,6 +972,12 @@ void ClientConnect (void) bot_relinkplayerlist(); + self.spectatortime = time; + if(blockSpectators) + { + sprint(self, strcat("^7You have to become a player within the next ", ftos(cvar("g_maxplayers_spectator_blocktime")), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n")); + } + self.jointime = time; } @@ -1446,20 +1454,61 @@ void ShowRespawnCountdown() void LeaveSpectatorMode() { - if(!cvar("teamplay") || cvar("g_campaign") || cvar("g_balance_teams")) { - self.classname = "player"; - if(cvar("g_campaign") || cvar("g_balance_teams") || cvar("g_balance_teams_force")) - JoinBestTeam(self, FALSE, TRUE); - if(cvar("g_campaign")) - campaign_bots_may_start = 1; - PutClientInServer(); - if(!(self.flags & FL_NOTARGET)) - bprint ("^4", self.netname, "^4 is playing now\n"); - centerprint(self,""); - return; - } else { - stuffcmd(self,"menu_showteamselect\n"); - return; + if(isJoinAllowed()) { + if(!cvar("teamplay") || cvar("g_campaign") || cvar("g_balance_teams")) { + self.classname = "player"; + if(cvar("g_campaign") || cvar("g_balance_teams") || cvar("g_balance_teams_force")) + JoinBestTeam(self, FALSE, TRUE); + if(cvar("g_campaign")) + campaign_bots_may_start = 1; + PutClientInServer(); + if(!(self.flags & FL_NOTARGET)) + bprint ("^4", self.netname, "^4 is playing now\n"); + centerprint(self,""); + return; + } else { + stuffcmd(self,"menu_showteamselect\n"); + return; + } + } + else { + //player may not join because of g_maxplayers is set + centerprint_atprio(self, CENTERPRIO_MAPVOTE, PREVENT_JOIN_TEXT); + } +} + +/** + * Determines whether the player is allowed to join. This depends on cvar + * g_maxplayers, if it isn't used this function always return TRUE, otherwise + * it checks whether the number of currently playing players exceeds g_maxplayers. + * @return bool TRUE if the player is allowed to join, false otherwise + */ +float isJoinAllowed() { + if (!cvar("g_maxplayers")) + return TRUE; + + local entity e; + local float currentlyPlaying; + FOR_EACH_REALPLAYER(e) { + if(e.classname == "player") + currentlyPlaying += 1; + } + if(currentlyPlaying < cvar("g_maxplayers")) + return TRUE; + + return FALSE; +} + +/** + * Checks whether the client is an observer or spectator, if so, he will get kicked after + * g_maxplayers_spectator_blocktime seconds + */ +void checkSpectatorBlock() { + if(self.classname == "spectator" || self.classname == "observer") { + if( time > (self.spectatortime + cvar("g_maxplayers_spectator_blocktime")) ) { + sprint(self, "^7You were kicked from the server because you are spectator and spectators aren't allowed at the moment.\n"); + dropclient(self); + } } } @@ -1474,6 +1523,9 @@ void() ctf_setstatus; .float vote_nagtime; void PlayerPreThink (void) { + if(blockSpectators) + checkSpectatorBlock(); + // version nagging if(self.version_nagtime) if(self.cvar_g_nexuizversion) diff --git a/data/qcsrc/server/clientcommands.qc b/data/qcsrc/server/clientcommands.qc index 454f7caa4..f2c9b18a7 100644 --- a/data/qcsrc/server/clientcommands.qc +++ b/data/qcsrc/server/clientcommands.qc @@ -451,16 +451,24 @@ void SV_ParseClientCommand(string s) { WaypointSprite_PlayerDead(); DistributeFragsAmongTeam(self, self.team, 1.0); self.classname = "observer"; + if(blockSpectators) + sprint(self, strcat("^7You have to become a player within the next ", ftos(cvar("g_maxplayers_spectator_blocktime")), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n")); PutClientInServer(); } } else if(argv(0) == "join") { if(!g_arena) if (self.classname != "player" && !lockteams) { - self.classname = "player"; - self.frags = 0; - bprint ("^4", self.netname, "^4 is playing now\n"); - PutClientInServer(); + if(isJoinAllowed()) { + self.classname = "player"; + self.frags = 0; + bprint ("^4", self.netname, "^4 is playing now\n"); + PutClientInServer(); + } + else { + //player may not join because of g_maxplayers is set + centerprint_atprio(self, CENTERPRIO_MAPVOTE, PREVENT_JOIN_TEXT); + } } } else if( argv(0) == "selectteam" ) { if( !cvar("teamplay") ) { diff --git a/data/qcsrc/server/defs.qh b/data/qcsrc/server/defs.qh index ca2a873ba..b583db7a3 100644 --- a/data/qcsrc/server/defs.qh +++ b/data/qcsrc/server/defs.qh @@ -279,11 +279,16 @@ void restartAnnouncer_Think(); entity readyNagger; //manages printing the ready-nag to active players who are not ready yet void readyNagger_Think(); float readyNagActive; //if set to 1, the readyNagger entity was already spawned (boolean) +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 +void checkSpectatorBlock(); .float winning; .float deaths; .float jointime; +float isJoinAllowed(); +#define PREVENT_JOIN_TEXT "^1You may not join the game at this time.\n\nThe player limit reached maximum capacity." .float spawnshieldtime; .float lms_nextcheck; diff --git a/data/qcsrc/server/gamecommand.qc b/data/qcsrc/server/gamecommand.qc index 766f502b5..37f92afc2 100644 --- a/data/qcsrc/server/gamecommand.qc +++ b/data/qcsrc/server/gamecommand.qc @@ -147,6 +147,21 @@ void GameCommand(string command) print("DB loaded.\n"); return; } + if (argv(0) == "nospectators") + { + blockSpectators = 1; + local entity plr; + FOR_EACH_CLIENT(plr) //give every spectator seconds time to become a player + { + if(plr.classname == "spectator" || plr.classname == "observer") + { + plr.spectatortime = time; + sprint(plr, strcat("^7You have to become a player within the next ", ftos(cvar("g_maxplayers_spectator_blocktime")), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n")); + } + } + bprint(strcat("^7All spectators will be automatically kicked when not joining the game after ", ftos(cvar("g_maxplayers_spectator_blocktime")), " seconds!\n")); + return; + } if (argv(0) == "lockteams") { if(teamplay) -- 2.39.2