Home | History | Annotate | Download | only in server
      1 /*
      2 Copyright (C) 1996-1997 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // sv_main.c -- server main program
     21 
     22 #include "qwsvdef.h"
     23 
     24 #define CHAN_AUTO   0
     25 #define CHAN_WEAPON 1
     26 #define CHAN_VOICE  2
     27 #define CHAN_ITEM   3
     28 #define CHAN_BODY   4
     29 
     30 /*
     31 =============================================================================
     32 
     33 Con_Printf redirection
     34 
     35 =============================================================================
     36 */
     37 
     38 char	outputbuf[8000];
     39 
     40 redirect_t	sv_redirected;
     41 
     42 extern cvar_t sv_phs;
     43 
     44 /*
     45 ==================
     46 SV_FlushRedirect
     47 ==================
     48 */
     49 void SV_FlushRedirect (void)
     50 {
     51 	char	send[8000+6];
     52 
     53 	if (sv_redirected == RD_PACKET)
     54 	{
     55 		send[0] = 0xff;
     56 		send[1] = 0xff;
     57 		send[2] = 0xff;
     58 		send[3] = 0xff;
     59 		send[4] = A2C_PRINT;
     60 		memcpy (send+5, outputbuf, strlen(outputbuf)+1);
     61 
     62 		NET_SendPacket (strlen(send)+1, send, net_from);
     63 	}
     64 	else if (sv_redirected == RD_CLIENT)
     65 	{
     66 		ClientReliableWrite_Begin (host_client, svc_print, strlen(outputbuf)+3);
     67 		ClientReliableWrite_Byte (host_client, PRINT_HIGH);
     68 		ClientReliableWrite_String (host_client, outputbuf);
     69 	}
     70 
     71 	// clear it
     72 	outputbuf[0] = 0;
     73 }
     74 
     75 
     76 /*
     77 ==================
     78 SV_BeginRedirect
     79 
     80   Send Con_Printf data to the remote client
     81   instead of the console
     82 ==================
     83 */
     84 void SV_BeginRedirect (redirect_t rd)
     85 {
     86 	sv_redirected = rd;
     87 	outputbuf[0] = 0;
     88 }
     89 
     90 void SV_EndRedirect (void)
     91 {
     92 	SV_FlushRedirect ();
     93 	sv_redirected = RD_NONE;
     94 }
     95 
     96 
     97 /*
     98 ================
     99 Con_Printf
    100 
    101 Handles cursor positioning, line wrapping, etc
    102 ================
    103 */
    104 #define	MAXPRINTMSG	4096
    105 // FIXME: make a buffer size safe vsprintf?
    106 void Con_Printf (char *fmt, ...)
    107 {
    108 	va_list		argptr;
    109 	char		msg[MAXPRINTMSG];
    110 
    111 	va_start (argptr,fmt);
    112 	vsprintf (msg,fmt,argptr);
    113 	va_end (argptr);
    114 
    115 	// add to redirected message
    116 	if (sv_redirected)
    117 	{
    118 		if (strlen (msg) + strlen(outputbuf) > sizeof(outputbuf) - 1)
    119 			SV_FlushRedirect ();
    120 		strcat (outputbuf, msg);
    121 		return;
    122 	}
    123 
    124 	Sys_Printf ("%s", msg);	// also echo to debugging console
    125 	if (sv_logfile)
    126 		fprintf (sv_logfile, "%s", msg);
    127 }
    128 
    129 /*
    130 ================
    131 Con_DPrintf
    132 
    133 A Con_Printf that only shows up if the "developer" cvar is set
    134 ================
    135 */
    136 void Con_DPrintf (char *fmt, ...)
    137 {
    138 	va_list		argptr;
    139 	char		msg[MAXPRINTMSG];
    140 
    141 	if (!developer.value)
    142 		return;
    143 
    144 	va_start (argptr,fmt);
    145 	vsprintf (msg,fmt,argptr);
    146 	va_end (argptr);
    147 
    148 	Con_Printf ("%s", msg);
    149 }
    150 
    151 /*
    152 =============================================================================
    153 
    154 EVENT MESSAGES
    155 
    156 =============================================================================
    157 */
    158 
    159 static void SV_PrintToClient(client_t *cl, int level, char *string)
    160 {
    161 	ClientReliableWrite_Begin (cl, svc_print, strlen(string)+3);
    162 	ClientReliableWrite_Byte (cl, level);
    163 	ClientReliableWrite_String (cl, string);
    164 }
    165 
    166 
    167 /*
    168 =================
    169 SV_ClientPrintf
    170 
    171 Sends text across to be displayed if the level passes
    172 =================
    173 */
    174 void SV_ClientPrintf (client_t *cl, int level, char *fmt, ...)
    175 {
    176 	va_list		argptr;
    177 	char		string[1024];
    178 
    179 	if (level < cl->messagelevel)
    180 		return;
    181 
    182 	va_start (argptr,fmt);
    183 	vsprintf (string, fmt,argptr);
    184 	va_end (argptr);
    185 
    186 	SV_PrintToClient(cl, level, string);
    187 }
    188 
    189 /*
    190 =================
    191 SV_BroadcastPrintf
    192 
    193 Sends text to all active clients
    194 =================
    195 */
    196 void SV_BroadcastPrintf (int level, char *fmt, ...)
    197 {
    198 	va_list		argptr;
    199 	char		string[1024];
    200 	client_t	*cl;
    201 	int			i;
    202 
    203 	va_start (argptr,fmt);
    204 	vsprintf (string, fmt,argptr);
    205 	va_end (argptr);
    206 
    207 	Sys_Printf ("%s", string);	// print to the console
    208 
    209 	for (i=0, cl = svs.clients ; i<MAX_CLIENTS ; i++, cl++)
    210 	{
    211 		if (level < cl->messagelevel)
    212 			continue;
    213 		if (!cl->state)
    214 			continue;
    215 
    216 		SV_PrintToClient(cl, level, string);
    217 	}
    218 }
    219 
    220 /*
    221 =================
    222 SV_BroadcastCommand
    223 
    224 Sends text to all active clients
    225 =================
    226 */
    227 void SV_BroadcastCommand (char *fmt, ...)
    228 {
    229 	va_list		argptr;
    230 	char		string[1024];
    231 
    232 	if (!sv.state)
    233 		return;
    234 	va_start (argptr,fmt);
    235 	vsprintf (string, fmt,argptr);
    236 	va_end (argptr);
    237 
    238 	MSG_WriteByte (&sv.reliable_datagram, svc_stufftext);
    239 	MSG_WriteString (&sv.reliable_datagram, string);
    240 }
    241 
    242 
    243 /*
    244 =================
    245 SV_Multicast
    246 
    247 Sends the contents of sv.multicast to a subset of the clients,
    248 then clears sv.multicast.
    249 
    250 MULTICAST_ALL	same as broadcast
    251 MULTICAST_PVS	send to clients potentially visible from org
    252 MULTICAST_PHS	send to clients potentially hearable from org
    253 =================
    254 */
    255 void SV_Multicast (vec3_t origin, int to)
    256 {
    257 	client_t	*client;
    258 	byte		*mask;
    259 	mleaf_t		*leaf;
    260 	int			leafnum;
    261 	int			j;
    262 	qboolean	reliable;
    263 
    264 	leaf = Mod_PointInLeaf (origin, sv.worldmodel);
    265 	if (!leaf)
    266 		leafnum = 0;
    267 	else
    268 		leafnum = leaf - sv.worldmodel->leafs;
    269 
    270 	reliable = false;
    271 
    272 	switch (to)
    273 	{
    274 	case MULTICAST_ALL_R:
    275 		reliable = true;	// intentional fallthrough
    276 	case MULTICAST_ALL:
    277 		mask = sv.pvs;		// leaf 0 is everything;
    278 		break;
    279 
    280 	case MULTICAST_PHS_R:
    281 		reliable = true;	// intentional fallthrough
    282 	case MULTICAST_PHS:
    283 		mask = sv.phs + leafnum * 4*((sv.worldmodel->numleafs+31)>>5);
    284 		break;
    285 
    286 	case MULTICAST_PVS_R:
    287 		reliable = true;	// intentional fallthrough
    288 	case MULTICAST_PVS:
    289 		mask = sv.pvs + leafnum * 4*((sv.worldmodel->numleafs+31)>>5);
    290 		break;
    291 
    292 	default:
    293 		mask = NULL;
    294 		SV_Error ("SV_Multicast: bad to:%i", to);
    295 	}
    296 
    297 	// send the data to all relevent clients
    298 	for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++)
    299 	{
    300 		if (client->state != cs_spawned)
    301 			continue;
    302 
    303 		if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) {
    304 			vec3_t delta;
    305 			VectorSubtract(origin, client->edict->v.origin, delta);
    306 			if (Length(delta) <= 1024)
    307 				goto inrange;
    308 		}
    309 
    310 		leaf = Mod_PointInLeaf (client->edict->v.origin, sv.worldmodel);
    311 		if (leaf)
    312 		{
    313 			// -1 is because pvs rows are 1 based, not 0 based like leafs
    314 			leafnum = leaf - sv.worldmodel->leafs - 1;
    315 			if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) )
    316 			{
    317 //				Con_Printf ("supressed multicast\n");
    318 				continue;
    319 			}
    320 		}
    321 
    322 inrange:
    323 		if (reliable) {
    324 			ClientReliableCheckBlock(client, sv.multicast.cursize);
    325 			ClientReliableWrite_SZ(client, sv.multicast.data, sv.multicast.cursize);
    326 		} else
    327 			SZ_Write (&client->datagram, sv.multicast.data, sv.multicast.cursize);
    328 	}
    329 
    330 	SZ_Clear (&sv.multicast);
    331 }
    332 
    333 
    334 /*
    335 ==================
    336 SV_StartSound
    337 
    338 Each entity can have eight independant sound sources, like voice,
    339 weapon, feet, etc.
    340 
    341 Channel 0 is an auto-allocate channel, the others override anything
    342 allready running on that entity/channel pair.
    343 
    344 An attenuation of 0 will play full volume everywhere in the level.
    345 Larger attenuations will drop off.  (max 4 attenuation)
    346 
    347 ==================
    348 */
    349 void SV_StartSound (edict_t *entity, int channel, char *sample, int volume,
    350     float attenuation)
    351 {
    352     int         sound_num;
    353     int			field_mask;
    354     int			i;
    355 	int			ent;
    356 	vec3_t		origin;
    357 	qboolean	use_phs;
    358 	qboolean	reliable = false;
    359 
    360 	if (volume < 0 || volume > 255)
    361 		SV_Error ("SV_StartSound: volume = %i", volume);
    362 
    363 	if (attenuation < 0 || attenuation > 4)
    364 		SV_Error ("SV_StartSound: attenuation = %f", attenuation);
    365 
    366 	if (channel < 0 || channel > 15)
    367 		SV_Error ("SV_StartSound: channel = %i", channel);
    368 
    369 // find precache number for sound
    370     for (sound_num=1 ; sound_num<MAX_SOUNDS
    371         && sv.sound_precache[sound_num] ; sound_num++)
    372         if (!strcmp(sample, sv.sound_precache[sound_num]))
    373             break;
    374 
    375     if ( sound_num == MAX_SOUNDS || !sv.sound_precache[sound_num] )
    376     {
    377         Con_Printf ("SV_StartSound: %s not precacheed\n", sample);
    378         return;
    379     }
    380 
    381 	ent = NUM_FOR_EDICT(entity);
    382 
    383 	if ((channel & 8) || !sv_phs.value)	// no PHS flag
    384 	{
    385 		if (channel & 8)
    386 			reliable = true; // sounds that break the phs are reliable
    387 		use_phs = false;
    388 		channel &= 7;
    389 	}
    390 	else
    391 		use_phs = true;
    392 
    393 //	if (channel == CHAN_BODY || channel == CHAN_VOICE)
    394 //		reliable = true;
    395 
    396 	channel = (ent<<3) | channel;
    397 
    398 	field_mask = 0;
    399 	if (volume != DEFAULT_SOUND_PACKET_VOLUME)
    400 		channel |= SND_VOLUME;
    401 	if (attenuation != DEFAULT_SOUND_PACKET_ATTENUATION)
    402 		channel |= SND_ATTENUATION;
    403 
    404 	// use the entity origin unless it is a bmodel
    405 	if (entity->v.solid == SOLID_BSP)
    406 	{
    407 		for (i=0 ; i<3 ; i++)
    408 			origin[i] = entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i]);
    409 	}
    410 	else
    411 	{
    412 		VectorCopy (entity->v.origin, origin);
    413 	}
    414 
    415 	MSG_WriteByte (&sv.multicast, svc_sound);
    416 	MSG_WriteShort (&sv.multicast, channel);
    417 	if (channel & SND_VOLUME)
    418 		MSG_WriteByte (&sv.multicast, volume);
    419 	if (channel & SND_ATTENUATION)
    420 		MSG_WriteByte (&sv.multicast, attenuation*64);
    421 	MSG_WriteByte (&sv.multicast, sound_num);
    422 	for (i=0 ; i<3 ; i++)
    423 		MSG_WriteCoord (&sv.multicast, origin[i]);
    424 
    425 	if (use_phs)
    426 		SV_Multicast (origin, reliable ? MULTICAST_PHS_R : MULTICAST_PHS);
    427 	else
    428 		SV_Multicast (origin, reliable ? MULTICAST_ALL_R : MULTICAST_ALL);
    429 }
    430 
    431 
    432 /*
    433 ===============================================================================
    434 
    435 FRAME UPDATES
    436 
    437 ===============================================================================
    438 */
    439 
    440 int		sv_nailmodel, sv_supernailmodel, sv_playermodel;
    441 
    442 void SV_FindModelNumbers (void)
    443 {
    444 	int		i;
    445 
    446 	sv_nailmodel = -1;
    447 	sv_supernailmodel = -1;
    448 	sv_playermodel = -1;
    449 
    450 	for (i=0 ; i<MAX_MODELS ; i++)
    451 	{
    452 		if (!sv.model_precache[i])
    453 			break;
    454 		if (!strcmp(sv.model_precache[i],"progs/spike.mdl"))
    455 			sv_nailmodel = i;
    456 		if (!strcmp(sv.model_precache[i],"progs/s_spike.mdl"))
    457 			sv_supernailmodel = i;
    458 		if (!strcmp(sv.model_precache[i],"progs/player.mdl"))
    459 			sv_playermodel = i;
    460 	}
    461 }
    462 
    463 
    464 /*
    465 ==================
    466 SV_WriteClientdataToMessage
    467 
    468 ==================
    469 */
    470 void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg)
    471 {
    472 	int		i;
    473 	edict_t	*other;
    474 	edict_t	*ent;
    475 
    476 	ent = client->edict;
    477 
    478 	// send the chokecount for r_netgraph
    479 	if (client->chokecount)
    480 	{
    481 		MSG_WriteByte (msg, svc_chokecount);
    482 		MSG_WriteByte (msg, client->chokecount);
    483 		client->chokecount = 0;
    484 	}
    485 
    486 	// send a damage message if the player got hit this frame
    487 	if (ent->v.dmg_take || ent->v.dmg_save)
    488 	{
    489 		other = PROG_TO_EDICT(ent->v.dmg_inflictor);
    490 		MSG_WriteByte (msg, svc_damage);
    491 		MSG_WriteByte (msg, ent->v.dmg_save);
    492 		MSG_WriteByte (msg, ent->v.dmg_take);
    493 		for (i=0 ; i<3 ; i++)
    494 			MSG_WriteCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i]));
    495 
    496 		ent->v.dmg_take = 0;
    497 		ent->v.dmg_save = 0;
    498 	}
    499 
    500 	// a fixangle might get lost in a dropped packet.  Oh well.
    501 	if ( ent->v.fixangle )
    502 	{
    503 		MSG_WriteByte (msg, svc_setangle);
    504 		for (i=0 ; i < 3 ; i++)
    505 			MSG_WriteAngle (msg, ent->v.angles[i] );
    506 		ent->v.fixangle = 0;
    507 	}
    508 }
    509 
    510 /*
    511 =======================
    512 SV_UpdateClientStats
    513 
    514 Performs a delta update of the stats array.  This should only be performed
    515 when a reliable message can be delivered this frame.
    516 =======================
    517 */
    518 void SV_UpdateClientStats (client_t *client)
    519 {
    520 	edict_t	*ent;
    521 	int		stats[MAX_CL_STATS];
    522 	int		i;
    523 
    524 	ent = client->edict;
    525 	memset (stats, 0, sizeof(stats));
    526 
    527 	// if we are a spectator and we are tracking a player, we get his stats
    528 	// so our status bar reflects his
    529 	if (client->spectator && client->spec_track > 0)
    530 		ent = svs.clients[client->spec_track - 1].edict;
    531 
    532 	stats[STAT_HEALTH] = ent->v.health;
    533 	stats[STAT_WEAPON] = SV_ModelIndex(PR_GetString(ent->v.weaponmodel));
    534 	stats[STAT_AMMO] = ent->v.currentammo;
    535 	stats[STAT_ARMOR] = ent->v.armorvalue;
    536 	stats[STAT_SHELLS] = ent->v.ammo_shells;
    537 	stats[STAT_NAILS] = ent->v.ammo_nails;
    538 	stats[STAT_ROCKETS] = ent->v.ammo_rockets;
    539 	stats[STAT_CELLS] = ent->v.ammo_cells;
    540 	if (!client->spectator)
    541 		stats[STAT_ACTIVEWEAPON] = ent->v.weapon;
    542 	// stuff the sigil bits into the high bits of items for sbar
    543 	stats[STAT_ITEMS] = (int)ent->v.items | ((int)pr_global_struct->serverflags << 28);
    544 
    545 	for (i=0 ; i<MAX_CL_STATS ; i++)
    546 		if (stats[i] != client->stats[i])
    547 		{
    548 			client->stats[i] = stats[i];
    549 			if (stats[i] >=0 && stats[i] <= 255)
    550 			{
    551 				ClientReliableWrite_Begin(client, svc_updatestat, 3);
    552 				ClientReliableWrite_Byte(client, i);
    553 				ClientReliableWrite_Byte(client, stats[i]);
    554 			}
    555 			else
    556 			{
    557 				ClientReliableWrite_Begin(client, svc_updatestatlong, 6);
    558 				ClientReliableWrite_Byte(client, i);
    559 				ClientReliableWrite_Long(client, stats[i]);
    560 			}
    561 		}
    562 }
    563 
    564 /*
    565 =======================
    566 SV_SendClientDatagram
    567 =======================
    568 */
    569 qboolean SV_SendClientDatagram (client_t *client)
    570 {
    571 	byte		buf[MAX_DATAGRAM];
    572 	sizebuf_t	msg;
    573 
    574 	msg.data = buf;
    575 	msg.maxsize = sizeof(buf);
    576 	msg.cursize = 0;
    577 	msg.allowoverflow = true;
    578 	msg.overflowed = false;
    579 
    580 	// add the client specific data to the datagram
    581 	SV_WriteClientdataToMessage (client, &msg);
    582 
    583 	// send over all the objects that are in the PVS
    584 	// this will include clients, a packetentities, and
    585 	// possibly a nails update
    586 	SV_WriteEntitiesToClient (client, &msg);
    587 
    588 	// copy the accumulated multicast datagram
    589 	// for this client out to the message
    590 	if (client->datagram.overflowed)
    591 		Con_Printf ("WARNING: datagram overflowed for %s\n", client->name);
    592 	else
    593 		SZ_Write (&msg, client->datagram.data, client->datagram.cursize);
    594 	SZ_Clear (&client->datagram);
    595 
    596 	// send deltas over reliable stream
    597 	if (Netchan_CanReliable (&client->netchan))
    598 		SV_UpdateClientStats (client);
    599 
    600 	if (msg.overflowed)
    601 	{
    602 		Con_Printf ("WARNING: msg overflowed for %s\n", client->name);
    603 		SZ_Clear (&msg);
    604 	}
    605 
    606 	// send the datagram
    607 	Netchan_Transmit (&client->netchan, msg.cursize, buf);
    608 
    609 	return true;
    610 }
    611 
    612 /*
    613 =======================
    614 SV_UpdateToReliableMessages
    615 =======================
    616 */
    617 void SV_UpdateToReliableMessages (void)
    618 {
    619 	int			i, j;
    620 	client_t *client;
    621 	eval_t *val;
    622 	edict_t *ent;
    623 
    624 // check for changes to be sent over the reliable streams to all clients
    625 	for (i=0, host_client = svs.clients ; i<MAX_CLIENTS ; i++, host_client++)
    626 	{
    627 		if (host_client->state != cs_spawned)
    628 			continue;
    629 		if (host_client->sendinfo)
    630 		{
    631 			host_client->sendinfo = false;
    632 			SV_FullClientUpdate (host_client, &sv.reliable_datagram);
    633 		}
    634 		if (host_client->old_frags != host_client->edict->v.frags)
    635 		{
    636 			for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
    637 			{
    638 				if (client->state < cs_connected)
    639 					continue;
    640 				ClientReliableWrite_Begin(client, svc_updatefrags, 4);
    641 				ClientReliableWrite_Byte(client, i);
    642 				ClientReliableWrite_Short(client, host_client->edict->v.frags);
    643 			}
    644 
    645 			host_client->old_frags = host_client->edict->v.frags;
    646 		}
    647 
    648 		// maxspeed/entgravity changes
    649 		ent = host_client->edict;
    650 
    651 		val = GetEdictFieldValue(ent, "gravity");
    652 		if (val && host_client->entgravity != val->_float) {
    653 			host_client->entgravity = val->_float;
    654 			ClientReliableWrite_Begin(host_client, svc_entgravity, 5);
    655 			ClientReliableWrite_Float(host_client, host_client->entgravity);
    656 		}
    657 		val = GetEdictFieldValue(ent, "maxspeed");
    658 		if (val && host_client->maxspeed != val->_float) {
    659 			host_client->maxspeed = val->_float;
    660 			ClientReliableWrite_Begin(host_client, svc_maxspeed, 5);
    661 			ClientReliableWrite_Float(host_client, host_client->maxspeed);
    662 		}
    663 
    664 	}
    665 
    666 	if (sv.datagram.overflowed)
    667 		SZ_Clear (&sv.datagram);
    668 
    669 	// append the broadcast messages to each client messages
    670 	for (j=0, client = svs.clients ; j<MAX_CLIENTS ; j++, client++)
    671 	{
    672 		if (client->state < cs_connected)
    673 			continue;	// reliables go to all connected or spawned
    674 
    675 		ClientReliableCheckBlock(client, sv.reliable_datagram.cursize);
    676 		ClientReliableWrite_SZ(client, sv.reliable_datagram.data, sv.reliable_datagram.cursize);
    677 
    678 		if (client->state != cs_spawned)
    679 			continue;	// datagrams only go to spawned
    680 		SZ_Write (&client->datagram
    681 			, sv.datagram.data
    682 			, sv.datagram.cursize);
    683 	}
    684 
    685 	SZ_Clear (&sv.reliable_datagram);
    686 	SZ_Clear (&sv.datagram);
    687 }
    688 
    689 #ifdef _WIN32
    690 #pragma optimize( "", off )
    691 #endif
    692 
    693 
    694 
    695 /*
    696 =======================
    697 SV_SendClientMessages
    698 =======================
    699 */
    700 void SV_SendClientMessages (void)
    701 {
    702 	int			i, j;
    703 	client_t	*c;
    704 
    705 // update frags, names, etc
    706 	SV_UpdateToReliableMessages ();
    707 
    708 // build individual updates
    709 	for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
    710 	{
    711 		if (!c->state)
    712 			continue;
    713 
    714 		if (c->drop) {
    715 			SV_DropClient(c);
    716 			c->drop = false;
    717 			continue;
    718 		}
    719 
    720 		// check to see if we have a backbuf to stick in the reliable
    721 		if (c->num_backbuf) {
    722 			// will it fit?
    723 			if (c->netchan.message.cursize + c->backbuf_size[0] <
    724 				c->netchan.message.maxsize) {
    725 
    726 				Con_DPrintf("%s: backbuf %d bytes\n",
    727 					c->name, c->backbuf_size[0]);
    728 
    729 				// it'll fit
    730 				SZ_Write(&c->netchan.message, c->backbuf_data[0],
    731 					c->backbuf_size[0]);
    732 
    733 				//move along, move along
    734 				for (j = 1; j < c->num_backbuf; j++) {
    735 					memcpy(c->backbuf_data[j - 1], c->backbuf_data[j],
    736 						c->backbuf_size[j]);
    737 					c->backbuf_size[j - 1] = c->backbuf_size[j];
    738 				}
    739 
    740 				c->num_backbuf--;
    741 				if (c->num_backbuf) {
    742 					memset(&c->backbuf, 0, sizeof(c->backbuf));
    743 					c->backbuf.data = c->backbuf_data[c->num_backbuf - 1];
    744 					c->backbuf.cursize = c->backbuf_size[c->num_backbuf - 1];
    745 					c->backbuf.maxsize = sizeof(c->backbuf_data[c->num_backbuf - 1]);
    746 				}
    747 			}
    748 		}
    749 
    750 		// if the reliable message overflowed,
    751 		// drop the client
    752 		if (c->netchan.message.overflowed)
    753 		{
    754 			SZ_Clear (&c->netchan.message);
    755 			SZ_Clear (&c->datagram);
    756 			SV_BroadcastPrintf (PRINT_HIGH, "%s overflowed\n", c->name);
    757 			Con_Printf ("WARNING: reliable overflow for %s\n",c->name);
    758 			SV_DropClient (c);
    759 			c->send_message = true;
    760 			c->netchan.cleartime = 0;	// don't choke this message
    761 		}
    762 
    763 		// only send messages if the client has sent one
    764 		// and the bandwidth is not choked
    765 		if (!c->send_message)
    766 			continue;
    767 		c->send_message = false;	// try putting this after choke?
    768 		if (!sv.paused && !Netchan_CanPacket (&c->netchan))
    769 		{
    770 			c->chokecount++;
    771 			continue;		// bandwidth choke
    772 		}
    773 
    774 		if (c->state == cs_spawned)
    775 			SV_SendClientDatagram (c);
    776 		else
    777 			Netchan_Transmit (&c->netchan, 0, NULL);	// just update reliable
    778 
    779 	}
    780 }
    781 
    782 #ifdef _WIN32
    783 #pragma optimize( "", on )
    784 #endif
    785 
    786 
    787 
    788 /*
    789 =======================
    790 SV_SendMessagesToAll
    791 
    792 FIXME: does this sequence right?
    793 =======================
    794 */
    795 void SV_SendMessagesToAll (void)
    796 {
    797 	int			i;
    798 	client_t	*c;
    799 
    800 	for (i=0, c = svs.clients ; i<MAX_CLIENTS ; i++, c++)
    801 		if (c->state)		// FIXME: should this only send to active?
    802 			c->send_message = true;
    803 
    804 	SV_SendClientMessages ();
    805 }
    806 
    807