void SV_RemoveBot (client_t *cl) { if (cl->state == cs_spawned) { if (!cl->spectator) { // call the prog function for removing a client // this will set the body to a dead frame, among other things pr_global_struct->self = EDICT_TO_PROG(cl->edict); PR_ExecuteProgram (PR_GLOBAL(ClientDisconnect)); } else if (SpectatorDisconnect) { // call the prog function for removing a client // this will set the body to a dead frame, among other things pr_global_struct->self = EDICT_TO_PROG(cl->edict); PR_ExecuteProgram (SpectatorDisconnect); } } Com_DPrintf ("Bot %s removed\n", cl->name.c_str()); cl->state = cs_free; // we don't have zombie bots :) cl->bot = false; cl->old_frags = 0; cl->name = ""; // cl->edict->inuse = false; cl->edict->v.frags = 0; cl->userinfo.clear(); SV_FreeDelayedPackets (cl); // send notification to all remaining clients SV_FullClientUpdate (cl, &sv.reliable_datagram); }
/* ================ SV_Shutdown Quake calls this before calling Sys_Quit or Sys_Error ================ */ void SV_Shutdown (char *finalmsg) { int i; SV_FinalMessage (finalmsg); PR_FreeStrings (); Master_Shutdown (); NET_ServerConfig (false); if (sv_fraglogfile) { fclose (sv_fraglogfile); sv_fraglogfile = NULL; } memset (&sv, 0, sizeof(sv)); sv.state = ss_dead; com_serveractive = false; for (i = 0; i < MAX_CLIENTS; i++) SV_FreeDelayedPackets(&svs.clients[i]); memset (svs.clients, 0, sizeof(svs.clients)); svs.lastuserid = 0; }
/* ================ SV_SaveSpawnparms Grabs the current state of the progs serverinfo flags and each client for saving across the transition to another level ================ */ void SV_SaveSpawnparms (void) { int i, j; if (!sv.state) return; // no progs loaded yet // serverflags is the only game related thing maintained svs.serverflags = pr_global_struct->serverflags; for (i=0, sv_client = svs.clients ; i<MAX_CLIENTS ; i++, sv_client++) { if (sv_client->state != cs_spawned) continue; if (sv_client->bot) { // bots are kicked on map change sv_client->state = cs_free; sv_client->bot = false; sv_client->name[0] = 0; memset (sv_client->userinfo, 0, sizeof(sv_client->userinfo)); SV_FreeDelayedPackets(sv_client); } else { // needs to reconnect sv_client->state = cs_connected; } // call the progs to get default spawn parms for the new client pr_global_struct->self = EDICT_TO_PROG(sv_client->edict); PR_ExecuteProgram (pr_global_struct->SetChangeParms); for (j=0 ; j<NUM_SPAWN_PARMS ; j++) sv_client->spawn_parms[j] = (&pr_global_struct->parm1)[j]; } }
/* ===================== SV_DropClient Called when the player is totally leaving the server, either willingly or unwillingly. This is NOT called if the entire server is quiting or crashing. ===================== */ void SV_DropClient (client_t *drop) { #ifdef MAUTH authclient_t *dropclient; #endif if (drop->bot) { SV_RemoveBot (drop); return; } // add the disconnect MSG_WriteByte (&drop->netchan.message, svc_disconnect); if (drop->state == cs_spawned) { if (!drop->spectator) { // call the prog function for removing a client // this will set the body to a dead frame, among other things pr_global_struct->self = EDICT_TO_PROG(drop->edict); PR_ExecuteProgram (pr_global_struct->ClientDisconnect); } else if (SpectatorDisconnect) { // call the prog function for removing a client // this will set the body to a dead frame, among other things pr_global_struct->self = EDICT_TO_PROG(drop->edict); PR_ExecuteProgram (SpectatorDisconnect); } } #ifdef MAUTH // remove client from auth queue... dropclient = SV_AuthListFind(&authclientq, Info_ValueForKey(drop->userinfo, "name")); if( dropclient ) SV_AuthListRemove (&authclientq, dropclient); #endif if (drop->spectator) Com_Printf ("Spectator %s removed\n",drop->name); else Com_Printf ("Client %s removed\n",drop->name); if (drop->download) { fclose (drop->download); drop->download = NULL; } if (drop->upload) { fclose (drop->upload); drop->upload = NULL; } *drop->uploadfn = 0; drop->state = cs_zombie; // become free in a few seconds drop->connection_started = svs.realtime; // for zombie timeout drop->old_frags = 0; drop->edict->v.frags = 0; // drop->edict->inuse = false; drop->name[0] = 0; memset (drop->userinfo, 0, sizeof(drop->userinfo)); SV_FreeDelayedPackets(drop); // send notification to all remaining clients SV_FullClientUpdate (drop, &sv.reliable_datagram); }