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