int i;
Con_Printf("Client \"%s\" dropped\n", host_client->name);
- // send any final messages (don't check for errors)
+ // make sure edict is not corrupt (from a level change for example)
+ host_client->edict = EDICT_NUM(host_client - svs.clients + 1);
+
if (host_client->netconnection)
{
// free the client (the body stays around)
MSG_WriteByte(&host_client->message, svc_disconnect);
NetConn_SendUnreliableMessage(host_client->netconnection, &host_client->message);
}
-
// break the net connection
NetConn_Close(host_client->netconnection);
host_client->netconnection = NULL;
+ }
- // LordHavoc: don't call QC if server is dead (avoids recursive
- // Host_Error in some mods when they run out of edicts)
- if (sv.active && host_client->edict && host_client->spawned)
- {
- // call the prog function for removing a client
- // this will set the body to a dead frame, among other things
- int saveSelf = pr_global_struct->self;
- pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
- PR_ExecuteProgram(pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing");
- pr_global_struct->self = saveSelf;
- }
+ // call qc ClientDisconnect function
+ // LordHavoc: don't call QC if server is dead (avoids recursive
+ // Host_Error in some mods when they run out of edicts)
+ if (host_client->active && sv.active && host_client->edict && host_client->spawned)
+ {
+ // call the prog function for removing a client
+ // this will set the body to a dead frame, among other things
+ int saveSelf = pr_global_struct->self;
+ pr_global_struct->self = EDICT_TO_PROG(host_client->edict);
+ PR_ExecuteProgram(pr_global_struct->ClientDisconnect, "QC function ClientDisconnect is missing");
+ pr_global_struct->self = saveSelf;
}
// remove leaving player from scoreboard
- // clear a fields that matter to DP_SV_CLIENTNAME and DP_SV_CLIENTCOLORS, and also frags
- ED_ClearEdict(host_client->edict);
//host_client->edict->v->netname = PR_SetString(host_client->name);
//if ((val = GETEDICTFIELDVALUE(host_client->edict, eval_clientcolors)))
// val->_float = 0;
EntityFrame4_FreeDatabase(host_client->entitydatabase4);
if (host_client->entitydatabase5)
EntityFrame5_FreeDatabase(host_client->entitydatabase5);
+
+ if (sv.active)
+ {
+ // clear a fields that matter to DP_SV_CLIENTNAME and DP_SV_CLIENTCOLORS, and also frags
+ ED_ClearEdict(host_client->edict);
+ }
+
// clear the client struct (this sets active to false)
memset(host_client, 0, sizeof(*host_client));
timeleft = (oldrealtime - realtime) + timecap;
if (timeleft > 0)
{
+ int msleft;
// don't totally hog the CPU
- if (timeleft >= 0.03)
- Sys_Sleep((int)(timeleft * 1000) - 10);
+ if (cls.state == ca_dedicated)
+ {
+ // if dedicated, try to use as little cpu as possible by waiting
+ // just a little longer than necessary
+ // (yes this means it doesn't quite keep up with the framerate)
+ msleft = (int)ceil(timeleft * 1000);
+ }
+ else
+ {
+ // if not dedicated, try to hit exactly a steady framerate by not
+ // sleeping the full amount
+ msleft = (int)floor(timeleft * 1000);
+ }
+ if (msleft > 0)
+ Sys_Sleep(msleft);
return false;
}
if (cls.state != ca_dedicated)
{
VID_Open();
+ CL_InitTEnts (); // We must wait after sound startup to load tent sounds
SCR_BeginLoadingPlaque();
MR_Init();
}