diff --git a/engine/server/server.h b/engine/server/server.h index 9c8f914c3..a82eb3b23 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -331,6 +331,7 @@ typedef struct client_s client_conn_state_t state; int spectator; // non-interactive + int redirect; qboolean sendinfo; // at end of frame, send info to all // this prevents malicious multiple broadcasts diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index cf50cae83..ce98d6cdb 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -532,10 +532,13 @@ void SV_DropClient (client_t *drop) Z_Free(drop->centerprintstring); drop->centerprintstring = NULL; - if (drop->spectator) - Con_Printf ("Spectator %s removed\n",drop->name); - else - Con_Printf ("Client %s removed\n",drop->name); + if (!drop->redirect) + { + if (drop->spectator) + Con_Printf ("Spectator %s removed\n",drop->name); + else + Con_Printf ("Client %s removed\n",drop->name); + } if (drop->download) { @@ -1674,6 +1677,7 @@ client_t *SVC_DirectConnect(void) int challenge; int huffcrc = 0; char guid[128] = ""; + qboolean redirect = false; int maxpacketentities; @@ -2096,8 +2100,20 @@ client_t *SVC_DirectConnect(void) if (svprogfuncs) { if (spectator && spectators >= maxspectators.ival) - newcl = NULL; + redirect = true; if (!spectator && clients >= maxclients.ival) + redirect = true; + } + else + { + if (clients >= maxclients.ival) + redirect = true; + } + + if (redirect) + { + extern cvar_t sv_fullredirect; + if (!*sv_fullredirect.string) newcl = NULL; } @@ -2383,7 +2399,10 @@ client_t *SVC_DirectConnect(void) { SV_AcceptMessage (protocol); - if (newcl->spectator) + if (redirect) + { + } + else if (newcl->spectator) { SV_BroadcastTPrintf(PRINT_LOW, STL_SPECTATORCONNECTED, newcl->name); // Con_Printf ("Spectator %s connected\n", newcl->name); @@ -2409,10 +2428,15 @@ client_t *SVC_DirectConnect(void) } newcl->sendinfo = true; - for (i = 0; i < sizeof(sv_motd)/sizeof(sv_motd[0]); i++) + if (redirect) + numssclients = 1; + else { - if (*sv_motd[i].string) - SV_ClientPrintf(newcl, PRINT_CHAT, "%s\n", sv_motd[i].string); + for (i = 0; i < sizeof(sv_motd)/sizeof(sv_motd[0]); i++) + { + if (*sv_motd[i].string) + SV_ClientPrintf(newcl, PRINT_CHAT, "%s\n", sv_motd[i].string); + } } SV_CheckRecentCrashes(newcl); @@ -2482,10 +2506,12 @@ client_t *SVC_DirectConnect(void) } newcl->controller = NULL; + if (!redirect) + { + Sys_ServerActivity(); - Sys_ServerActivity(); - - PIN_ShowMessages(newcl); + PIN_ShowMessages(newcl); + } if (ISNQCLIENT(newcl)) { @@ -2494,6 +2520,7 @@ client_t *SVC_DirectConnect(void) SVNQ_New_f(); } + newcl->redirect = redirect; return newcl; diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index cc557cb22..b80d94c41 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -44,6 +44,7 @@ cvar_t sv_spectalk = SCVAR("sv_spectalk", "1"); cvar_t sv_mapcheck = SCVAR("sv_mapcheck", "1"); +cvar_t sv_fullredirect = CVARD("sv_fullredirect", "", "This is the ip:port to redirect players to when the server is full"); cvar_t sv_antilag = CVARFD("sv_antilag", "1", CVAR_SERVERINFO, "Attempt to backdate impacts to compensate for lag. 0=completely off. 1=mod-controlled. 2=forced, which might break certain uses of traceline."); cvar_t sv_antilag_frac = CVARF("sv_antilag_frac", "1", CVAR_SERVERINFO); cvar_t sv_cheatpc = CVAR("sv_cheatpc", "125"); @@ -218,6 +219,14 @@ void SV_New_f (void) if (host_client->state == cs_spawned) return; + if (host_client->redirect) + { + char *msg = va("connect \"%s\"\n", sv_fullredirect.string); + ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(msg)); + ClientReliableWrite_String (host_client, msg); + return; + } + /* splitt delay host_client->state = cs_connected; host_client->connection_started = realtime; @@ -406,6 +415,14 @@ void SVNQ_New_f (void) char message[2048]; int i; + if (host_client->redirect) + { + char *msg = va("connect \"%s\"\n", sv_fullredirect.string); + ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(msg)); + ClientReliableWrite_String (host_client, msg); + return; + } + if (!host_client->pextknown) { MSG_WriteByte (&host_client->netchan.message, svc_stufftext); @@ -3252,9 +3269,16 @@ The client is going to disconnect, so remove the connection immediately */ void SV_Drop_f (void) { + extern cvar_t sv_fullredirect; + SV_EndRedirect (); - if (!host_client->spectator) - SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTDROPPED, host_client->name); + if (host_client->redirect) + SV_BroadcastPrintf (PRINT_HIGH, "%s redirected to %s\n", host_client->name, sv_fullredirect.string); + else + { + if (!host_client->spectator) + SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTDROPPED, host_client->name); + } SV_DropClient (host_client); } @@ -6562,6 +6586,7 @@ void SV_UserInit (void) Cvar_Register (&sv_spectalk, cvargroup_servercontrol); Cvar_Register (&sv_mapcheck, cvargroup_servercontrol); + Cvar_Register (&sv_fullredirect, cvargroup_servercontrol); Cvar_Register (&sv_antilag, cvargroup_servercontrol); Cvar_Register (&sv_antilag_frac, cvargroup_servercontrol); Cvar_Register (&sv_cheatpc, cvargroup_servercontrol);