diff --git a/qw/include/server.h b/qw/include/server.h index 3f45bfffc..6ca83db08 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -139,6 +139,8 @@ typedef struct typedef struct client_s { sv_client_state_t state; + qboolean prespawned; + qboolean spawned; int spectator; // non-interactive diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 3e605cf81..16caeaf25 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -840,6 +840,8 @@ SVC_DirectConnect (void) Netchan_Setup (&newcl->netchan, adr, qport); newcl->state = cs_connected; + newcl->prespawned = false; + newcl->spawned = false; svs.num_clients++; newcl->datagram.allowoverflow = true; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index ad6004bb1..4b7ca6ad3 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -304,6 +304,8 @@ SV_PreSpawn_f (void) host_client->checksum = check; } + host_client->prespawned = true; + if (buf == sv.num_signon_buffers - 1) command = va ("cmd spawn %i 0\n", svs.spawncount); else @@ -345,6 +347,14 @@ SV_Spawn_f (void) SV_New_f (); return; } +// make sure they're not trying to cheat by spawning without prespawning + if (host_client->prespawned == false) { + SV_BroadcastPrintf (PRINT_HIGH, + va ("%s has been kicked for trying to spawn before prespawning!\n", + host_client->name)); + SV_DropClient (host_client); + return; + } n = atoi (Cmd_Argv (2)); @@ -354,6 +364,9 @@ SV_Spawn_f (void) SV_New_f (); return; } + + host_client->spawned = true; + // send all current names, colors, and frag counts // FIXME: is this a good thing? SZ_Clear (&host_client->netchan.message); @@ -465,6 +478,16 @@ SV_Begin_f (void) return; } + // make sure they're not trying to cheat by beginning without spawning + if (host_client->spawned == false) { + SV_BroadcastPrintf (PRINT_HIGH, + va ("%s has been kicked for trying to begin before spawning!\n" + "Have a nice day!\n", // 1 string! + host_client->name)); + SV_DropClient (host_client); + return; + } + if (host_client->spectator) { SV_SpawnSpectator ();