diff --git a/engine/server/server.h b/engine/server/server.h index 7bd153de1..8b5f5c85a 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -1074,6 +1074,7 @@ void VoteFlushAll(void); void SV_SetUpClientEdict (client_t *cl, edict_t *ent); void SV_UpdateToReliableMessages (void); void SV_FlushBroadcasts (void); +qboolean SV_CanTrack(client_t *client, int entity); void SV_DarkPlacesDownloadChunk(client_t *cl, sizebuf_t *msg); void SV_New_f (void); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index f5118b226..7a3e5ffe4 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -2376,29 +2376,15 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t * clst.spectator = 0; if (client->spectator) { - client_t *s; - - if (client->spec_track > 0 && client->spec_track <= sv.allocated_client_slots) - s = &svs.clients[client->spec_track-1]; - else - s = NULL; - if (!s || s->state != cs_spawned) + if (client->spec_track > 0) { - if (client->spec_track) - { - Con_Printf("Client was spectating now-invalid entity: %i\n", client->spec_track); - client->spec_track = 0; - } - s = NULL; - } + edict_t *s = EDICT_NUM(svprogfuncs, client->spec_track); - if (s) - { clst.spectator = 2; - clst.mins = svs.clients[client->spec_track-1].edict->v->mins; - clst.maxs = svs.clients[client->spec_track-1].edict->v->maxs; - clst.health = svs.clients[client->spec_track-1].edict->v->health; - clst.weaponframe = svs.clients[client->spec_track-1].edict->v->weaponframe; + clst.mins = s->v->mins; + clst.maxs = s->v->maxs; + clst.health = s->v->health; + clst.weaponframe = s->v->weaponframe; } else { diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index caa7d064e..643d35c87 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1573,7 +1573,7 @@ void SV_CalcClientStats(client_t *client, int statsi[MAX_CL_STATS], float statsf // if we are a spectator and we are tracking a player, we get his stats // so our status bar reflects his if (client->spectator && client->spec_track > 0) - ent = svs.clients[client->spec_track - 1].edict; + ent = EDICT_NUM(svprogfuncs, client->spec_track); #ifdef HLSERVER if (svs.gametype == GT_HALFLIFE) @@ -1844,6 +1844,13 @@ void SV_UpdateClientStats (client_t *client, int pnum) } } +qboolean SV_CanTrack(client_t *client, int entity) +{ + if (entity < 0 || entity > sv.allocated_client_slots || svs.clients[entity-1].state != cs_spawned || svs.clients[entity-1].spectator) + return false; + return true; +} + /* ======================= SV_SendClientDatagram @@ -1862,6 +1869,12 @@ qboolean SV_SendClientDatagram (client_t *client) msg.overflowed = false; msg.prim = client->datagram.prim; + if (client->spec_track && !SV_CanTrack(client, client->spec_track)) + { + client->spec_track = 0; + client->edict->v->goalentity = 0; + } + if (client->protocol != SCP_FITZ666 && !client->netchan.fragmentsize) msg.maxsize = MAX_DATAGRAM; diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 4c3c3059e..e4b2879fb 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -1643,7 +1643,7 @@ void SV_Begin_Core(client_t *split) { //keep the spectator tracking the player from the previous map if (split->spec_track > 0) - split->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, svs.clients[split->spec_track-1].edict); + split->edict->v->goalentity = EDICT_TO_PROG(svprogfuncs, EDICT_NUM(svprogfuncs, split->spec_track)); else split->edict->v->goalentity = 0; @@ -2379,7 +2379,7 @@ void SV_VoiceSendPacket(client_t *client, sizebuf_t *buf) send = true; /*if you're spectating, you can hear whatever your tracked player can hear*/ - if (host_client->spectator && host_client->spec_track) + if (host_client->spectator && host_client->spec_track && host_client->spec_track <= sv.allocated_client_slots) if (ring->receiver[(host_client->spec_track-1)>>3] & (1<<((host_client->spec_track-1)&3))) send = true; @@ -3471,8 +3471,7 @@ void SV_PTrack_f (void) } #endif - if (i < 0 || i >= sv.allocated_client_slots || svs.clients[i].state != cs_spawned || - svs.clients[i].spectator) + if (!SV_CanTrack(host_client, i+1)) { SV_ClientTPrintf (host_client, PRINT_HIGH, STL_INVALIDTRACKCLIENT); host_client->spec_track = 0;