Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

sv_snapshot.c (18804B)


      1 /*
      2 ===========================================================================
      3 Copyright (C) 1999-2005 Id Software, Inc.
      4 
      5 This file is part of Quake III Arena source code.
      6 
      7 Quake III Arena source code is free software; you can redistribute it
      8 and/or modify it under the terms of the GNU General Public License as
      9 published by the Free Software Foundation; either version 2 of the License,
     10 or (at your option) any later version.
     11 
     12 Quake III Arena source code is distributed in the hope that it will be
     13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 GNU General Public License for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with Foobar; if not, write to the Free Software
     19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     20 ===========================================================================
     21 */
     22 
     23 #include "server.h"
     24 
     25 
     26 /*
     27 =============================================================================
     28 
     29 Delta encode a client frame onto the network channel
     30 
     31 A normal server packet will look like:
     32 
     33 4	sequence number (high bit set if an oversize fragment)
     34 <optional reliable commands>
     35 1	svc_snapshot
     36 4	last client reliable command
     37 4	serverTime
     38 1	lastframe for delta compression
     39 1	snapFlags
     40 1	areaBytes
     41 <areabytes>
     42 <playerstate>
     43 <packetentities>
     44 
     45 =============================================================================
     46 */
     47 
     48 /*
     49 =============
     50 SV_EmitPacketEntities
     51 
     52 Writes a delta update of an entityState_t list to the message.
     53 =============
     54 */
     55 static void SV_EmitPacketEntities( clientSnapshot_t *from, clientSnapshot_t *to, msg_t *msg ) {
     56 	entityState_t	*oldent, *newent;
     57 	int		oldindex, newindex;
     58 	int		oldnum, newnum;
     59 	int		from_num_entities;
     60 
     61 	// generate the delta update
     62 	if ( !from ) {
     63 		from_num_entities = 0;
     64 	} else {
     65 		from_num_entities = from->num_entities;
     66 	}
     67 
     68 	newent = NULL;
     69 	oldent = NULL;
     70 	newindex = 0;
     71 	oldindex = 0;
     72 	while ( newindex < to->num_entities || oldindex < from_num_entities ) {
     73 		if ( newindex >= to->num_entities ) {
     74 			newnum = 9999;
     75 		} else {
     76 			newent = &svs.snapshotEntities[(to->first_entity+newindex) % svs.numSnapshotEntities];
     77 			newnum = newent->number;
     78 		}
     79 
     80 		if ( oldindex >= from_num_entities ) {
     81 			oldnum = 9999;
     82 		} else {
     83 			oldent = &svs.snapshotEntities[(from->first_entity+oldindex) % svs.numSnapshotEntities];
     84 			oldnum = oldent->number;
     85 		}
     86 
     87 		if ( newnum == oldnum ) {
     88 			// delta update from old position
     89 			// because the force parm is qfalse, this will not result
     90 			// in any bytes being emited if the entity has not changed at all
     91 			MSG_WriteDeltaEntity (msg, oldent, newent, qfalse );
     92 			oldindex++;
     93 			newindex++;
     94 			continue;
     95 		}
     96 
     97 		if ( newnum < oldnum ) {
     98 			// this is a new entity, send it from the baseline
     99 			MSG_WriteDeltaEntity (msg, &sv.svEntities[newnum].baseline, newent, qtrue );
    100 			newindex++;
    101 			continue;
    102 		}
    103 
    104 		if ( newnum > oldnum ) {
    105 			// the old entity isn't present in the new message
    106 			MSG_WriteDeltaEntity (msg, oldent, NULL, qtrue );
    107 			oldindex++;
    108 			continue;
    109 		}
    110 	}
    111 
    112 	MSG_WriteBits( msg, (MAX_GENTITIES-1), GENTITYNUM_BITS );	// end of packetentities
    113 }
    114 
    115 
    116 
    117 /*
    118 ==================
    119 SV_WriteSnapshotToClient
    120 ==================
    121 */
    122 static void SV_WriteSnapshotToClient( client_t *client, msg_t *msg ) {
    123 	clientSnapshot_t	*frame, *oldframe;
    124 	int					lastframe;
    125 	int					i;
    126 	int					snapFlags;
    127 
    128 	// this is the snapshot we are creating
    129 	frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];
    130 
    131 	// try to use a previous frame as the source for delta compressing the snapshot
    132 	if ( client->deltaMessage <= 0 || client->state != CS_ACTIVE ) {
    133 		// client is asking for a retransmit
    134 		oldframe = NULL;
    135 		lastframe = 0;
    136 	} else if ( client->netchan.outgoingSequence - client->deltaMessage 
    137 		>= (PACKET_BACKUP - 3) ) {
    138 		// client hasn't gotten a good message through in a long time
    139 		Com_DPrintf ("%s: Delta request from out of date packet.\n", client->name);
    140 		oldframe = NULL;
    141 		lastframe = 0;
    142 	} else {
    143 		// we have a valid snapshot to delta from
    144 		oldframe = &client->frames[ client->deltaMessage & PACKET_MASK ];
    145 		lastframe = client->netchan.outgoingSequence - client->deltaMessage;
    146 
    147 		// the snapshot's entities may still have rolled off the buffer, though
    148 		if ( oldframe->first_entity <= svs.nextSnapshotEntities - svs.numSnapshotEntities ) {
    149 			Com_DPrintf ("%s: Delta request from out of date entities.\n", client->name);
    150 			oldframe = NULL;
    151 			lastframe = 0;
    152 		}
    153 	}
    154 
    155 	MSG_WriteByte (msg, svc_snapshot);
    156 
    157 	// NOTE, MRE: now sent at the start of every message from server to client
    158 	// let the client know which reliable clientCommands we have received
    159 	//MSG_WriteLong( msg, client->lastClientCommand );
    160 
    161 	// send over the current server time so the client can drift
    162 	// its view of time to try to match
    163 	MSG_WriteLong (msg, svs.time);
    164 
    165 	// what we are delta'ing from
    166 	MSG_WriteByte (msg, lastframe);
    167 
    168 	snapFlags = svs.snapFlagServerBit;
    169 	if ( client->rateDelayed ) {
    170 		snapFlags |= SNAPFLAG_RATE_DELAYED;
    171 	}
    172 	if ( client->state != CS_ACTIVE ) {
    173 		snapFlags |= SNAPFLAG_NOT_ACTIVE;
    174 	}
    175 
    176 	MSG_WriteByte (msg, snapFlags);
    177 
    178 	// send over the areabits
    179 	MSG_WriteByte (msg, frame->areabytes);
    180 	MSG_WriteData (msg, frame->areabits, frame->areabytes);
    181 
    182 	// delta encode the playerstate
    183 	if ( oldframe ) {
    184 		MSG_WriteDeltaPlayerstate( msg, &oldframe->ps, &frame->ps );
    185 	} else {
    186 		MSG_WriteDeltaPlayerstate( msg, NULL, &frame->ps );
    187 	}
    188 
    189 	// delta encode the entities
    190 	SV_EmitPacketEntities (oldframe, frame, msg);
    191 
    192 	// padding for rate debugging
    193 	if ( sv_padPackets->integer ) {
    194 		for ( i = 0 ; i < sv_padPackets->integer ; i++ ) {
    195 			MSG_WriteByte (msg, svc_nop);
    196 		}
    197 	}
    198 }
    199 
    200 
    201 /*
    202 ==================
    203 SV_UpdateServerCommandsToClient
    204 
    205 (re)send all server commands the client hasn't acknowledged yet
    206 ==================
    207 */
    208 void SV_UpdateServerCommandsToClient( client_t *client, msg_t *msg ) {
    209 	int		i;
    210 
    211 	// write any unacknowledged serverCommands
    212 	for ( i = client->reliableAcknowledge + 1 ; i <= client->reliableSequence ; i++ ) {
    213 		MSG_WriteByte( msg, svc_serverCommand );
    214 		MSG_WriteLong( msg, i );
    215 		MSG_WriteString( msg, client->reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
    216 	}
    217 	client->reliableSent = client->reliableSequence;
    218 }
    219 
    220 /*
    221 =============================================================================
    222 
    223 Build a client snapshot structure
    224 
    225 =============================================================================
    226 */
    227 
    228 #define	MAX_SNAPSHOT_ENTITIES	1024
    229 typedef struct {
    230 	int		numSnapshotEntities;
    231 	int		snapshotEntities[MAX_SNAPSHOT_ENTITIES];	
    232 } snapshotEntityNumbers_t;
    233 
    234 /*
    235 =======================
    236 SV_QsortEntityNumbers
    237 =======================
    238 */
    239 static int QDECL SV_QsortEntityNumbers( const void *a, const void *b ) {
    240 	int	*ea, *eb;
    241 
    242 	ea = (int *)a;
    243 	eb = (int *)b;
    244 
    245 	if ( *ea == *eb ) {
    246 		Com_Error( ERR_DROP, "SV_QsortEntityStates: duplicated entity" );
    247 	}
    248 
    249 	if ( *ea < *eb ) {
    250 		return -1;
    251 	}
    252 
    253 	return 1;
    254 }
    255 
    256 
    257 /*
    258 ===============
    259 SV_AddEntToSnapshot
    260 ===============
    261 */
    262 static void SV_AddEntToSnapshot( svEntity_t *svEnt, sharedEntity_t *gEnt, snapshotEntityNumbers_t *eNums ) {
    263 	// if we have already added this entity to this snapshot, don't add again
    264 	if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
    265 		return;
    266 	}
    267 	svEnt->snapshotCounter = sv.snapshotCounter;
    268 
    269 	// if we are full, silently discard entities
    270 	if ( eNums->numSnapshotEntities == MAX_SNAPSHOT_ENTITIES ) {
    271 		return;
    272 	}
    273 
    274 	eNums->snapshotEntities[ eNums->numSnapshotEntities ] = gEnt->s.number;
    275 	eNums->numSnapshotEntities++;
    276 }
    277 
    278 /*
    279 ===============
    280 SV_AddEntitiesVisibleFromPoint
    281 ===============
    282 */
    283 static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame, 
    284 									snapshotEntityNumbers_t *eNums, qboolean portal ) {
    285 	int		e, i;
    286 	sharedEntity_t *ent;
    287 	svEntity_t	*svEnt;
    288 	int		l;
    289 	int		clientarea, clientcluster;
    290 	int		leafnum;
    291 	int		c_fullsend;
    292 	byte	*clientpvs;
    293 	byte	*bitvector;
    294 
    295 	// during an error shutdown message we may need to transmit
    296 	// the shutdown message after the server has shutdown, so
    297 	// specfically check for it
    298 	if ( !sv.state ) {
    299 		return;
    300 	}
    301 
    302 	leafnum = CM_PointLeafnum (origin);
    303 	clientarea = CM_LeafArea (leafnum);
    304 	clientcluster = CM_LeafCluster (leafnum);
    305 
    306 	// calculate the visible areas
    307 	frame->areabytes = CM_WriteAreaBits( frame->areabits, clientarea );
    308 
    309 	clientpvs = CM_ClusterPVS (clientcluster);
    310 
    311 	c_fullsend = 0;
    312 
    313 	for ( e = 0 ; e < sv.num_entities ; e++ ) {
    314 		ent = SV_GentityNum(e);
    315 
    316 		// never send entities that aren't linked in
    317 		if ( !ent->r.linked ) {
    318 			continue;
    319 		}
    320 
    321 		if (ent->s.number != e) {
    322 			Com_DPrintf ("FIXING ENT->S.NUMBER!!!\n");
    323 			ent->s.number = e;
    324 		}
    325 
    326 		// entities can be flagged to explicitly not be sent to the client
    327 		if ( ent->r.svFlags & SVF_NOCLIENT ) {
    328 			continue;
    329 		}
    330 
    331 		// entities can be flagged to be sent to only one client
    332 		if ( ent->r.svFlags & SVF_SINGLECLIENT ) {
    333 			if ( ent->r.singleClient != frame->ps.clientNum ) {
    334 				continue;
    335 			}
    336 		}
    337 		// entities can be flagged to be sent to everyone but one client
    338 		if ( ent->r.svFlags & SVF_NOTSINGLECLIENT ) {
    339 			if ( ent->r.singleClient == frame->ps.clientNum ) {
    340 				continue;
    341 			}
    342 		}
    343 		// entities can be flagged to be sent to a given mask of clients
    344 		if ( ent->r.svFlags & SVF_CLIENTMASK ) {
    345 			if (frame->ps.clientNum >= 32)
    346 				Com_Error( ERR_DROP, "SVF_CLIENTMASK: cientNum > 32\n" );
    347 			if (~ent->r.singleClient & (1 << frame->ps.clientNum))
    348 				continue;
    349 		}
    350 
    351 		svEnt = SV_SvEntityForGentity( ent );
    352 
    353 		// don't double add an entity through portals
    354 		if ( svEnt->snapshotCounter == sv.snapshotCounter ) {
    355 			continue;
    356 		}
    357 
    358 		// broadcast entities are always sent
    359 		if ( ent->r.svFlags & SVF_BROADCAST ) {
    360 			SV_AddEntToSnapshot( svEnt, ent, eNums );
    361 			continue;
    362 		}
    363 
    364 		// ignore if not touching a PV leaf
    365 		// check area
    366 		if ( !CM_AreasConnected( clientarea, svEnt->areanum ) ) {
    367 			// doors can legally straddle two areas, so
    368 			// we may need to check another one
    369 			if ( !CM_AreasConnected( clientarea, svEnt->areanum2 ) ) {
    370 				continue;		// blocked by a door
    371 			}
    372 		}
    373 
    374 		bitvector = clientpvs;
    375 
    376 		// check individual leafs
    377 		if ( !svEnt->numClusters ) {
    378 			continue;
    379 		}
    380 		l = 0;
    381 		for ( i=0 ; i < svEnt->numClusters ; i++ ) {
    382 			l = svEnt->clusternums[i];
    383 			if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
    384 				break;
    385 			}
    386 		}
    387 
    388 		// if we haven't found it to be visible,
    389 		// check overflow clusters that coudln't be stored
    390 		if ( i == svEnt->numClusters ) {
    391 			if ( svEnt->lastCluster ) {
    392 				for ( ; l <= svEnt->lastCluster ; l++ ) {
    393 					if ( bitvector[l >> 3] & (1 << (l&7) ) ) {
    394 						break;
    395 					}
    396 				}
    397 				if ( l == svEnt->lastCluster ) {
    398 					continue;	// not visible
    399 				}
    400 			} else {
    401 				continue;
    402 			}
    403 		}
    404 
    405 		// add it
    406 		SV_AddEntToSnapshot( svEnt, ent, eNums );
    407 
    408 		// if its a portal entity, add everything visible from its camera position
    409 		if ( ent->r.svFlags & SVF_PORTAL ) {
    410 			if ( ent->s.generic1 ) {
    411 				vec3_t dir;
    412 				VectorSubtract(ent->s.origin, origin, dir);
    413 				if ( VectorLengthSquared(dir) > (float) ent->s.generic1 * ent->s.generic1 ) {
    414 					continue;
    415 				}
    416 			}
    417 			SV_AddEntitiesVisibleFromPoint( ent->s.origin2, frame, eNums, qtrue );
    418 		}
    419 
    420 	}
    421 }
    422 
    423 /*
    424 =============
    425 SV_BuildClientSnapshot
    426 
    427 Decides which entities are going to be visible to the client, and
    428 copies off the playerstate and areabits.
    429 
    430 This properly handles multiple recursive portals, but the render
    431 currently doesn't.
    432 
    433 For viewing through other player's eyes, clent can be something other than client->gentity
    434 =============
    435 */
    436 static void SV_BuildClientSnapshot( client_t *client ) {
    437 	vec3_t						org;
    438 	clientSnapshot_t			*frame;
    439 	snapshotEntityNumbers_t		entityNumbers;
    440 	int							i;
    441 	sharedEntity_t				*ent;
    442 	entityState_t				*state;
    443 	svEntity_t					*svEnt;
    444 	sharedEntity_t				*clent;
    445 	int							clientNum;
    446 	playerState_t				*ps;
    447 
    448 	// bump the counter used to prevent double adding
    449 	sv.snapshotCounter++;
    450 
    451 	// this is the frame we are creating
    452 	frame = &client->frames[ client->netchan.outgoingSequence & PACKET_MASK ];
    453 
    454 	// clear everything in this snapshot
    455 	entityNumbers.numSnapshotEntities = 0;
    456 	Com_Memset( frame->areabits, 0, sizeof( frame->areabits ) );
    457 
    458   // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=62
    459 	frame->num_entities = 0;
    460 	
    461 	clent = client->gentity;
    462 	if ( !clent || client->state == CS_ZOMBIE ) {
    463 		return;
    464 	}
    465 
    466 	// grab the current playerState_t
    467 	ps = SV_GameClientNum( client - svs.clients );
    468 	frame->ps = *ps;
    469 
    470 	// never send client's own entity, because it can
    471 	// be regenerated from the playerstate
    472 	clientNum = frame->ps.clientNum;
    473 	if ( clientNum < 0 || clientNum >= MAX_GENTITIES ) {
    474 		Com_Error( ERR_DROP, "SV_SvEntityForGentity: bad gEnt" );
    475 	}
    476 	svEnt = &sv.svEntities[ clientNum ];
    477 
    478 	svEnt->snapshotCounter = sv.snapshotCounter;
    479 
    480 	// find the client's viewpoint
    481 	VectorCopy( ps->origin, org );
    482 	org[2] += ps->viewheight;
    483 
    484 	// add all the entities directly visible to the eye, which
    485 	// may include portal entities that merge other viewpoints
    486 	SV_AddEntitiesVisibleFromPoint( org, frame, &entityNumbers, qfalse );
    487 
    488 	// if there were portals visible, there may be out of order entities
    489 	// in the list which will need to be resorted for the delta compression
    490 	// to work correctly.  This also catches the error condition
    491 	// of an entity being included twice.
    492 	qsort( entityNumbers.snapshotEntities, entityNumbers.numSnapshotEntities, 
    493 		sizeof( entityNumbers.snapshotEntities[0] ), SV_QsortEntityNumbers );
    494 
    495 	// now that all viewpoint's areabits have been OR'd together, invert
    496 	// all of them to make it a mask vector, which is what the renderer wants
    497 	for ( i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++ ) {
    498 		((int *)frame->areabits)[i] = ((int *)frame->areabits)[i] ^ -1;
    499 	}
    500 
    501 	// copy the entity states out
    502 	frame->num_entities = 0;
    503 	frame->first_entity = svs.nextSnapshotEntities;
    504 	for ( i = 0 ; i < entityNumbers.numSnapshotEntities ; i++ ) {
    505 		ent = SV_GentityNum(entityNumbers.snapshotEntities[i]);
    506 		state = &svs.snapshotEntities[svs.nextSnapshotEntities % svs.numSnapshotEntities];
    507 		*state = ent->s;
    508 		svs.nextSnapshotEntities++;
    509 		// this should never hit, map should always be restarted first in SV_Frame
    510 		if ( svs.nextSnapshotEntities >= 0x7FFFFFFE ) {
    511 			Com_Error(ERR_FATAL, "svs.nextSnapshotEntities wrapped");
    512 		}
    513 		frame->num_entities++;
    514 	}
    515 }
    516 
    517 
    518 /*
    519 ====================
    520 SV_RateMsec
    521 
    522 Return the number of msec a given size message is supposed
    523 to take to clear, based on the current rate
    524 ====================
    525 */
    526 #define	HEADER_RATE_BYTES	48		// include our header, IP header, and some overhead
    527 static int SV_RateMsec( client_t *client, int messageSize ) {
    528 	int		rate;
    529 	int		rateMsec;
    530 
    531 	// individual messages will never be larger than fragment size
    532 	if ( messageSize > 1500 ) {
    533 		messageSize = 1500;
    534 	}
    535 	rate = client->rate;
    536 	if ( sv_maxRate->integer ) {
    537 		if ( sv_maxRate->integer < 1000 ) {
    538 			Cvar_Set( "sv_MaxRate", "1000" );
    539 		}
    540 		if ( sv_maxRate->integer < rate ) {
    541 			rate = sv_maxRate->integer;
    542 		}
    543 	}
    544 	rateMsec = ( messageSize + HEADER_RATE_BYTES ) * 1000 / rate;
    545 
    546 	return rateMsec;
    547 }
    548 
    549 /*
    550 =======================
    551 SV_SendMessageToClient
    552 
    553 Called by SV_SendClientSnapshot and SV_SendClientGameState
    554 =======================
    555 */
    556 void SV_SendMessageToClient( msg_t *msg, client_t *client ) {
    557 	int			rateMsec;
    558 
    559 	// record information about the message
    560 	client->frames[client->netchan.outgoingSequence & PACKET_MASK].messageSize = msg->cursize;
    561 	client->frames[client->netchan.outgoingSequence & PACKET_MASK].messageSent = svs.time;
    562 	client->frames[client->netchan.outgoingSequence & PACKET_MASK].messageAcked = -1;
    563 
    564 	// send the datagram
    565 	SV_Netchan_Transmit( client, msg );	//msg->cursize, msg->data );
    566 
    567 	// set nextSnapshotTime based on rate and requested number of updates
    568 
    569 	// local clients get snapshots every frame
    570 	// TTimo - https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
    571 	// added sv_lanForceRate check
    572 	if ( client->netchan.remoteAddress.type == NA_LOOPBACK || (sv_lanForceRate->integer && Sys_IsLANAddress (client->netchan.remoteAddress)) ) {
    573 		client->nextSnapshotTime = svs.time - 1;
    574 		return;
    575 	}
    576 	
    577 	// normal rate / snapshotMsec calculation
    578 	rateMsec = SV_RateMsec( client, msg->cursize );
    579 
    580 	if ( rateMsec < client->snapshotMsec ) {
    581 		// never send more packets than this, no matter what the rate is at
    582 		rateMsec = client->snapshotMsec;
    583 		client->rateDelayed = qfalse;
    584 	} else {
    585 		client->rateDelayed = qtrue;
    586 	}
    587 
    588 	client->nextSnapshotTime = svs.time + rateMsec;
    589 
    590 	// don't pile up empty snapshots while connecting
    591 	if ( client->state != CS_ACTIVE ) {
    592 		// a gigantic connection message may have already put the nextSnapshotTime
    593 		// more than a second away, so don't shorten it
    594 		// do shorten if client is downloading
    595 		if ( !*client->downloadName && client->nextSnapshotTime < svs.time + 1000 ) {
    596 			client->nextSnapshotTime = svs.time + 1000;
    597 		}
    598 	}
    599 }
    600 
    601 
    602 /*
    603 =======================
    604 SV_SendClientSnapshot
    605 
    606 Also called by SV_FinalMessage
    607 
    608 =======================
    609 */
    610 void SV_SendClientSnapshot( client_t *client ) {
    611 	byte		msg_buf[MAX_MSGLEN];
    612 	msg_t		msg;
    613 
    614 	// build the snapshot
    615 	SV_BuildClientSnapshot( client );
    616 
    617 	// bots need to have their snapshots build, but
    618 	// the query them directly without needing to be sent
    619 	if ( client->gentity && client->gentity->r.svFlags & SVF_BOT ) {
    620 		return;
    621 	}
    622 
    623 	MSG_Init (&msg, msg_buf, sizeof(msg_buf));
    624 	msg.allowoverflow = qtrue;
    625 
    626 	// NOTE, MRE: all server->client messages now acknowledge
    627 	// let the client know which reliable clientCommands we have received
    628 	MSG_WriteLong( &msg, client->lastClientCommand );
    629 
    630 	// (re)send any reliable server commands
    631 	SV_UpdateServerCommandsToClient( client, &msg );
    632 
    633 	// send over all the relevant entityState_t
    634 	// and the playerState_t
    635 	SV_WriteSnapshotToClient( client, &msg );
    636 
    637 	// Add any download data if the client is downloading
    638 	SV_WriteDownloadToClient( client, &msg );
    639 
    640 	// check for overflow
    641 	if ( msg.overflowed ) {
    642 		Com_Printf ("WARNING: msg overflowed for %s\n", client->name);
    643 		MSG_Clear (&msg);
    644 	}
    645 
    646 	SV_SendMessageToClient( &msg, client );
    647 }
    648 
    649 
    650 /*
    651 =======================
    652 SV_SendClientMessages
    653 =======================
    654 */
    655 void SV_SendClientMessages( void ) {
    656 	int			i;
    657 	client_t	*c;
    658 
    659 	// send a message to each connected client
    660 	for (i=0, c = svs.clients ; i < sv_maxclients->integer ; i++, c++) {
    661 		if (!c->state) {
    662 			continue;		// not connected
    663 		}
    664 
    665 		if ( svs.time < c->nextSnapshotTime ) {
    666 			continue;		// not time yet
    667 		}
    668 
    669 		// send additional message fragments if the last message
    670 		// was too large to send at once
    671 		if ( c->netchan.unsentFragments ) {
    672 			c->nextSnapshotTime = svs.time + 
    673 				SV_RateMsec( c, c->netchan.unsentLength - c->netchan.unsentFragmentStart );
    674 			SV_Netchan_TransmitNextFragment( c );
    675 			continue;
    676 		}
    677 
    678 		// generate and send a new message
    679 		SV_SendClientSnapshot( c );
    680 	}
    681 }
    682