1 /*
2 Copyright (C) 1997-2001 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 "server.h"
23 #include "mvd.h"
24
25 static int demo_msglen;
26 static byte demo_data[MAX_PACKETLEN];
27
28 /*
29 =============================================================================
30
31 MISC
32
33 =============================================================================
34 */
35
36 char sv_outputbuf[SV_OUTPUTBUF_LENGTH];
37
SV_FlushRedirect(int sv_redirected,char * outputbuf)38 void SV_FlushRedirect( int sv_redirected, char *outputbuf ) {
39 if( sv_redirected == RD_PACKET ) {
40 Netchan_OutOfBandPrint( NS_SERVER, &net_from, "print\n%s", outputbuf );
41 } else if( sv_redirected == RD_CLIENT ) {
42 MSG_WriteByte( svc_print );
43 MSG_WriteByte( PRINT_HIGH );
44 MSG_WriteString( outputbuf );
45 SV_ClientAddMessage( sv_client, MSG_RELIABLE|MSG_CLEAR );
46 }
47 }
48
49 /*
50 =======================
51 SV_RateDrop
52
53 Returns qtrue if the client is over its current
54 bandwidth estimation and should not be sent another packet
55 =======================
56 */
SV_RateDrop(client_t * client)57 static qboolean SV_RateDrop( client_t *client ) {
58 int total;
59 int i;
60
61 // never drop over the loopback
62 if( NET_IsLocalAddress( &client->netchan->remote_address ) ) {
63 return qfalse;
64 }
65 if( sv_lan_force_rate->integer && NET_IsLANAddress(
66 &client->netchan->remote_address ) )
67 {
68 return qfalse;
69 }
70
71 total = 0;
72 for( i = 0; i < RATE_MESSAGES; i++ ) {
73 total += client->message_size[i];
74 }
75
76 if( total > client->rate ) {
77 client->surpressCount++;
78 client->message_size[sv.framenum % RATE_MESSAGES] = 0;
79 return qtrue;
80 }
81
82 return qfalse;
83 }
84
SV_CalcSendTime(client_t * client,int messageSize)85 void SV_CalcSendTime( client_t *client, int messageSize ) {
86 int delta;
87
88 if( messageSize == -1 ) {
89 return;
90 }
91
92 // never drop over the loopback
93 if( NET_IsLocalAddress( &client->netchan->remote_address ) ) {
94 client->sendTime = 0;
95 return;
96 }
97
98 if( sv_lan_force_rate->integer && NET_IsLANAddress(
99 &client->netchan->remote_address ) )
100 {
101 client->sendTime = 0;
102 return;
103 }
104
105 client->message_size[sv.framenum % RATE_MESSAGES] = messageSize;
106
107 delta = messageSize * 1000 / client->rate;
108 client->sendTime = svs.realtime + delta;
109 }
110
111 /*
112 =============================================================================
113
114 EVENT MESSAGES
115
116 =============================================================================
117 */
118
119
120 /*
121 =================
122 SV_ClientPrintf
123
124 Sends text across to be displayed if the level passes.
125 NOT archived in MVD stream.
126 =================
127 */
SV_ClientPrintf(client_t * client,int level,const char * fmt,...)128 void SV_ClientPrintf( client_t *client, int level, const char *fmt, ... ) {
129 va_list argptr;
130 char string[MAX_STRING_CHARS];
131
132 if( level < client->messagelevel )
133 return;
134
135 va_start( argptr, fmt );
136 Q_vsnprintf( string, sizeof( string ), fmt, argptr );
137 va_end( argptr );
138
139 MSG_WriteByte( svc_print );
140 MSG_WriteByte( level );
141 MSG_WriteString( string );
142
143 SV_ClientAddMessage( client, MSG_RELIABLE|MSG_CLEAR );
144
145 }
146
147 /*
148 =================
149 SV_BroadcastPrintf
150
151 Sends text to all active clients, including MVD clients.
152 NOT archived in MVD stream.
153 =================
154 */
SV_BroadcastPrintf(int level,const char * fmt,...)155 void SV_BroadcastPrintf( int level, const char *fmt, ... ) {
156 va_list argptr;
157 char string[MAX_STRING_CHARS];
158 client_t *client;
159 int i;
160
161 va_start( argptr, fmt );
162 Q_vsnprintf( string, sizeof( string ), fmt, argptr );
163 va_end( argptr );
164
165 MSG_WriteByte( svc_print );
166 MSG_WriteByte( level );
167 MSG_WriteString( string );
168
169 // echo to console
170 if( dedicated->integer ) {
171 // mask off high bits
172 for( i = 0; string[i]; i++ )
173 string[i] &= 127;
174 Com_Printf( "%s", string );
175 }
176
177 FOR_EACH_CLIENT( client ) {
178 if( client->state != cs_spawned )
179 continue;
180 if( level < client->messagelevel )
181 continue;
182 SV_ClientAddMessage( client, MSG_RELIABLE );
183 }
184
185 SZ_Clear( &msg_write );
186 }
187
188 /*
189 =================
190 SV_BroadcastCommand
191
192 Sends command to all active clients, including MVD clients.
193 NOT archived in MVD stream.
194 =================
195 */
SV_BroadcastCommand(const char * fmt,...)196 void SV_BroadcastCommand( const char *fmt, ... ) {
197 va_list argptr;
198 char string[MAX_STRING_CHARS];
199 client_t *client;
200
201 if( !sv.state )
202 return;
203 va_start( argptr, fmt );
204 Q_vsnprintf( string, sizeof( string ), fmt, argptr );
205 va_end( argptr );
206
207 MSG_WriteByte( svc_stufftext );
208 MSG_WriteString( string );
209
210 FOR_EACH_CLIENT( client ) {
211 if( client->state < cs_connected )
212 continue;
213 SV_ClientAddMessage( client, MSG_RELIABLE );
214 }
215
216 SZ_Clear( &msg_write );
217 }
218
219
220 /*
221 =================
222 SV_Multicast
223
224 Sends the contents of the write buffer to a subset of the clients,
225 then clears the write buffer.
226
227 Archived in MVD stream.
228
229 MULTICAST_ALL same as broadcast (origin can be NULL)
230 MULTICAST_PVS send to clients potentially visible from org
231 MULTICAST_PHS send to clients potentially hearable from org
232 =================
233 */
SV_Multicast(vec3_t origin,multicast_t to)234 void SV_Multicast( vec3_t origin, multicast_t to ) {
235 client_t *client;
236 byte *mask;
237 cleaf_t *leaf;
238 int cluster;
239 int area1, area2;
240 int flags;
241 vec3_t org;
242 player_state_t *ps;
243
244 flags = 0;
245
246 switch( to ) {
247 case MULTICAST_ALL_R:
248 flags |= MSG_RELIABLE; // intentional fallthrough
249 case MULTICAST_ALL:
250 area1 = 0;
251 cluster = 0;
252 mask = NULL;
253 break;
254
255 case MULTICAST_PHS_R:
256 flags |= MSG_RELIABLE; // intentional fallthrough
257 case MULTICAST_PHS:
258 leaf = CM_PointLeaf( &sv.cm, origin );
259 area1 = CM_LeafArea( leaf );
260 cluster = CM_LeafCluster( leaf );
261 mask = CM_ClusterPHS( &sv.cm, cluster );
262 break;
263
264 case MULTICAST_PVS_R:
265 flags |= MSG_RELIABLE; // intentional fallthrough
266 case MULTICAST_PVS:
267 leaf = CM_PointLeaf( &sv.cm, origin );
268 area1 = CM_LeafArea( leaf );
269 cluster = CM_LeafCluster( leaf );
270 mask = CM_ClusterPVS( &sv.cm, cluster );
271 break;
272
273 default:
274 mask = NULL;
275 area1 = 0;
276 Com_Error( ERR_DROP, "SV_Multicast: bad to: %i", to );
277 }
278
279 // send the data to all relevent clients
280 FOR_EACH_CLIENT( client ) {
281 if( client->state < cs_connected ) {
282 continue;
283 }
284 if( client->protocol == PROTOCOL_VERSION_MVD ) {
285 client->AddMulticast( client, origin, to );
286 continue;
287 }
288 if( !( flags & MSG_RELIABLE ) ) {
289 /* do not send unreliables to connecting clients */
290 if( client->state != cs_spawned || client->download ||
291 client->nodata )
292 {
293 continue;
294 }
295 }
296
297 if( mask ) {
298 // find the client's PVS
299 ps = &client->edict->client->ps;
300 VectorMA( ps->viewoffset, 0.125f, ps->pmove.origin, org );
301 leaf = CM_PointLeaf( &sv.cm, org );
302 area2 = CM_LeafArea( leaf );
303 if( !CM_AreasConnected( &sv.cm, area1, area2 ) )
304 continue;
305 cluster = CM_LeafCluster( leaf );
306 if( !Q_IsBitSet( mask, cluster ) ) {
307 continue;
308 }
309 }
310
311 SV_ClientAddMessage( client, flags );
312
313 }
314
315 // if doing a serverrecord, store everything
316 MVD_RecMulticast( origin, to );
317
318 /* clear the buffer */
319 SZ_Clear( &msg_write );
320
321 }
322
323
324 /*
325 ==================
326 SV_StartSound
327
328 Each entity can have eight independant sound sources, like voice,
329 weapon, feet, etc.
330
331 If cahnnel & 8, the sound will be sent to everyone, not just
332 things in the PHS.
333
334 FIXME: if entity isn't in PHS, they must be forced to be sent or
335 have the origin explicitly sent.
336
337 Channel 0 is an auto-allocate channel, the others override anything
338 already running on that entity/channel pair.
339
340 An attenuation of 0 will play full volume everywhere in the level.
341 Larger attenuations will drop off. (max 4 attenuation)
342
343 Timeofs can range from 0.0 to 0.1 to cause sounds to be started
344 later in the frame than they normally would.
345
346 If origin is NULL, the origin is determined from the entity origin
347 or the midpoint of the entity box for bmodels.
348 ==================
349 */
SV_StartSound(vec3_t origin,edict_t * entity,int channel,int soundindex,float volume,float attenuation,float timeofs)350 void SV_StartSound( vec3_t origin, edict_t *entity, int channel,
351 int soundindex, float volume,
352 float attenuation, float timeofs )
353 {
354 int sendchan;
355 int flags;
356 int ent;
357 vec3_t origin_v;
358 vec3_t mid;
359 qboolean use_phs;
360
361 if( volume < 0 || volume > 1.0 )
362 Com_Error( ERR_DROP, "SV_StartSound: volume = %f", volume );
363
364 if( attenuation < 0 || attenuation > 4 )
365 Com_Error( ERR_DROP, "SV_StartSound: attenuation = %f", attenuation );
366
367 if( timeofs < 0 || timeofs > 0.255 )
368 Com_Error( ERR_DROP, "SV_StartSound: timeofs = %f", timeofs );
369
370 ent = NUM_FOR_EDICT( entity );
371
372 if( channel & 8 ) { // no PHS flag
373 use_phs = qfalse;
374 channel &= 7;
375 } else {
376 use_phs = qtrue;
377 }
378
379 sendchan = ( ent << 3 ) | ( channel & 7 );
380
381 flags = 0;
382 if( volume != DEFAULT_SOUND_PACKET_VOLUME )
383 flags |= SND_VOLUME;
384 if( attenuation != DEFAULT_SOUND_PACKET_ATTENUATION )
385 flags |= SND_ATTENUATION;
386
387 // always send the entity number for channel overrides
388 flags |= SND_ENT;
389
390 if( timeofs )
391 flags |= SND_OFFSET;
392
393 // if the sound doesn't attenuate,send it to everyone
394 // (global radio chatter, voiceovers, etc)
395 if( attenuation == ATTN_NONE )
396 use_phs = qfalse;
397
398 // the client doesn't know that bmodels have weird origins
399 // the origin can also be explicitly set
400 if( ent == 0 || ( entity->svflags & SVF_NOCLIENT ) ||
401 entity->solid == SOLID_BSP || origin )
402 flags |= SND_POS;
403
404 // use the entity origin unless it is a bmodel or explicitly specified
405 if( !origin ) {
406 origin = origin_v;
407 if( ent == 0 ) {
408 VectorClear( origin_v );
409 } else if( entity->solid == SOLID_BSP ) {
410 VectorAdd( entity->mins, entity->maxs, mid );
411 VectorMA( entity->s.origin, 0.5f, mid, origin_v );
412 } else {
413 VectorCopy( entity->s.origin, origin_v );
414 }
415 }
416
417 MSG_WriteByte( svc_sound );
418 MSG_WriteByte( flags );
419 MSG_WriteByte( soundindex );
420
421 if( flags & SND_VOLUME )
422 MSG_WriteByte( volume * 255 );
423 if( flags & SND_ATTENUATION )
424 MSG_WriteByte( attenuation * 64 );
425 if( flags & SND_OFFSET )
426 MSG_WriteByte( timeofs * 1000 );
427
428 if( flags & SND_ENT )
429 MSG_WriteShort( sendchan );
430
431 if( flags & SND_POS )
432 MSG_WritePos( origin );
433
434 if( channel & CHAN_RELIABLE ) {
435 if( use_phs )
436 SV_Multicast( origin, MULTICAST_PHS_R );
437 else
438 SV_Multicast( origin, MULTICAST_ALL_R );
439 } else {
440 if( use_phs )
441 SV_Multicast( origin, MULTICAST_PHS );
442 else
443 SV_Multicast( origin, MULTICAST_ALL );
444 }
445 }
446
447 /*
448 =======================
449 SV_ClientAddMessage
450
451 Adds contents of the current write buffer to client's message list.
452 Does NOT clean the buffer for multicast delivery purpose,
453 unless told otherwise.
454 =======================
455 */
SV_ClientAddMessage(client_t * client,int flags)456 void SV_ClientAddMessage( client_t *client, int flags ) {
457 if( !msg_write.cursize ) {
458 return;
459 }
460
461 client->AddMessage( client, msg_write.data, msg_write.cursize,
462 ( flags & MSG_RELIABLE ) ? qtrue : qfalse );
463
464 if( sv_debug_send->integer > 1 ) {
465 if( flags & MSG_RELIABLE ) {
466 Com_Printf( "AddRel( %s ): %i bytes\n",
467 client->name, msg_write.cursize );
468 } else {
469 Com_Printf( "AddMsg( %s ): %i bytes\n",
470 client->name, msg_write.cursize );
471 }
472 }
473
474 if( flags & MSG_CLEAR ) {
475 SZ_Clear( &msg_write );
476 }
477 }
478
479 /*
480 ===============================================================================
481
482 FRAME UPDATES - OLD CLIENTS
483
484 ===============================================================================
485 */
486
SV_OldClientAddMessage(client_t * client,byte * data,int length,qboolean reliable)487 void SV_OldClientAddMessage( client_t *client, byte *data,
488 int length, qboolean reliable )
489 {
490 clientMessage_t *msg;
491
492 if( length > client->netchan->maxpacketlen ) {
493 if( reliable ) {
494 SV_DropClient( client, "oversize reliable message" );
495 } else {
496 Com_DPrintf( "Dumped oversize unreliable for %s\n", client->name );
497 }
498 return;
499 }
500
501 msg = ( clientMessage_t * )client->freeMsgList.first;
502 if( !msg ) {
503 Com_WPrintf( "Out of message slots for %s!\n", client->name );
504 if( reliable ) {
505 SV_OldClientClearMessages( client );
506 SV_DropClient( client, "no slot for reliable message" );
507 }
508 return;
509 }
510
511 if( length > MSGQUEUE_MALLOC_TRESHOLD ) {
512 msg->data = SV_Malloc( length );
513 } else {
514 msg->data = msg->localBuffer;
515 }
516
517 memcpy( msg->data, data, length );
518 msg->cursize = length;
519 msg->reliable = reliable;
520
521 List_DeleteElem( msg );
522 List_Append( &client->usedMsgList, msg );
523 }
524
SV_OldClientRemoveMessage(client_t * client,clientMessage_t * msg)525 static void SV_OldClientRemoveMessage( client_t *client, clientMessage_t *msg )
526 {
527 if( msg->cursize > MSGQUEUE_MALLOC_TRESHOLD ) {
528 Z_Free( msg->data );
529 }
530
531 msg->data = NULL;
532 msg->cursize = 0;
533
534 List_DeleteElem( msg );
535 List_Append( &client->freeMsgList, msg );
536 }
537
SV_OldClientClearMessages(client_t * client)538 void SV_OldClientClearMessages( client_t *client ) {
539 listElem_t *elem, *next;
540
541 for( elem = client->usedMsgList.first; elem; elem = next ) {
542 next = elem->next;
543 SV_OldClientRemoveMessage( client, ( clientMessage_t * )elem );
544 }
545
546 }
547
548
549 /*
550 =======================
551 SV_OldClient_SendReliableMessages
552
553 This should be the only place data is
554 ever written to client->netchan.message
555 =======================
556 */
SV_OldClientWriteReliableMessages(client_t * client,int maxSize)557 void SV_OldClientWriteReliableMessages( client_t *client, int maxSize ) {
558 listElem_t *elem, *next;
559 clientMessage_t *msg;
560 int count;
561
562 if( client->netchan->reliable_length ) {
563 if( sv_debug_send->integer > 1 ) {
564 Com_Printf( "SndRel( %s ): unacked reliable\n", client->name );
565 }
566 return; // there is still outgoing reliable message pending
567 }
568
569 // find at least one reliable message to send
570 count = 0;
571 for( elem = client->usedMsgList.first; elem; elem = next ) {
572 next = elem->next;
573 msg = ( clientMessage_t * )elem;
574 if( !msg->reliable ) {
575 continue;
576 }
577
578 // stop if this msg doesn't fit (reliables must be delivered in order)
579 if( client->netchan->message.cursize + msg->cursize > maxSize ) {
580 if( !count ) {
581 Com_WPrintf( "Overflow on the first reliable message "
582 "for %s (should not happen).\n", client->name );
583 }
584 break;
585 }
586
587 if( sv_debug_send->integer > 1 ) {
588 Com_Printf( "SndRel( %s ): %i bytes\n", client->name,
589 msg->cursize );
590 }
591
592 SZ_Write( &client->netchan->message, msg->data, msg->cursize );
593 SV_OldClientRemoveMessage( client, msg );
594 count++;
595 }
596
597 }
598
599
600 /*
601 =======================
602 OldClient_SendDatagram
603 =======================
604 */
SV_OldClientWriteDatagram(client_t * client)605 void SV_OldClientWriteDatagram( client_t *client ) {
606 listElem_t *elem, *next;
607 clientMessage_t *msg;
608 int cursize, maxsize;
609 sizebuf_t compressed;
610 byte compressed_data[MAX_PACKETLEN_WRITABLE];
611
612 maxsize = client->netchan->maxpacketlen;
613 if( client->netchan->reliable_length ) {
614 // there is still unacked reliable message pending
615 maxsize -= client->netchan->reliable_length;
616 } else {
617 // find at least one reliable message to send
618 // and make sure to reserve space for it
619 for( elem = client->usedMsgList.first; elem; elem = elem->next ) {
620 msg = ( clientMessage_t * )elem;
621 if( msg->reliable ) {
622 maxsize -= msg->cursize;
623 break;
624 }
625 }
626 }
627
628 // send over all the relevant entity_state_t
629 // and the player_state_t
630 client->WriteFrame( client );
631 if( msg_write.cursize > maxsize ) {
632 if( sv_debug_send->integer ) {
633 Com_Printf( S_COLOR_BLUE"Frame overflowed for %s, ", client->name );
634 }
635 if( client->protocol != PROTOCOL_VERSION_DEFAULT ) {
636 SZ_Init( &compressed, compressed_data, sizeof( compressed_data ) );
637
638 if( sv_debug_send->integer ) {
639 Com_Printf( "deflating data... " );
640 }
641
642 // compress the frame
643 if( Com_ZLibDeflateBuffer( &msg_write, &compressed ) ) {
644 cursize = msg_write.cursize;
645 SZ_Clear( &msg_write );
646
647 if( compressed.cursize <= maxsize ) {
648 if( sv_debug_send->integer ) {
649 Com_Printf( "succeeded: %i --> %i\n",
650 cursize, compressed.cursize );
651 }
652
653 MSG_WriteByte( svc_zpacket );
654 MSG_WriteShort( compressed.cursize );
655 MSG_WriteShort( cursize );
656 MSG_WriteData( compressed.data, compressed.cursize );
657 } else {
658 if( sv_debug_send->integer ) {
659 Com_Printf( "failed: %i --> %i\n",
660 cursize, compressed.cursize );
661 }
662 }
663 } else {
664 if( sv_debug_send->integer ) {
665 Com_Printf( "deflate failed\n" );
666 }
667 SZ_Clear( &msg_write );
668 }
669 } else {
670 if( sv_debug_send->integer ) {
671 Com_Printf( "clearing frame\n" );
672 }
673 SZ_Clear( &msg_write );
674 }
675 }
676
677 // now try to write unreliable messages
678 // it is necessary for this to be after the WriteEntities
679 // so that entity references will be current
680 if( msg_write.cursize + 4 <= maxsize ) {
681 // temp entities first
682 for( elem = client->usedMsgList.first; elem; elem = next ) {
683 next = elem->next;
684 msg = ( clientMessage_t * )elem;
685 if( msg->reliable ) {
686 continue;
687 }
688 if( msg->data[0] != svc_temp_entity ) {
689 continue;
690 }
691 // ignore some low-priority effects, these checks come from r1q2
692 if( msg->data[1] == TE_BLOOD || msg->data[1] == TE_SPLASH ) {
693 continue;
694 }
695 if( msg->data[1] == TE_GUNSHOT || msg->data[1] == TE_BULLET_SPARKS
696 || msg->data[1] == TE_SHOTGUN )
697 {
698 continue;
699 }
700
701 // if this msg fits, write it
702 if( msg_write.cursize + msg->cursize <= maxsize ) {
703 MSG_WriteData( msg->data, msg->cursize );
704 }
705
706 SV_OldClientRemoveMessage( client, msg );
707 }
708
709 if( msg_write.cursize + 4 <= maxsize ) {
710 // then sounds
711 for( elem = client->usedMsgList.first; elem; elem = next ) {
712 next = elem->next;
713 msg = ( clientMessage_t * )elem;
714 if( msg->reliable ) {
715 continue;
716 }
717 if( msg->data[0] != svc_sound ) {
718 continue;
719 }
720
721 // if this msg fits, write it
722 if( msg_write.cursize + msg->cursize <= maxsize ) {
723 MSG_WriteData( msg->data, msg->cursize );
724 }
725
726 SV_OldClientRemoveMessage( client, msg );
727 }
728
729 if( msg_write.cursize + 4 <= maxsize ) {
730 // then everything else left
731 for( elem = client->usedMsgList.first; elem; elem = next ) {
732 next = elem->next;
733 msg = ( clientMessage_t * )elem;
734 if( msg->reliable ) {
735 continue;
736 }
737
738 // if this msg fits, write it
739 if( msg_write.cursize + msg->cursize <= maxsize ) {
740 MSG_WriteData( msg->data, msg->cursize );
741 }
742
743 SV_OldClientRemoveMessage( client, msg );
744 }
745 }
746 }
747 }
748
749 // clear all unreliable messages still left
750 for( elem = client->usedMsgList.first; elem; elem = next ) {
751 next = elem->next;
752 msg = ( clientMessage_t * )elem;
753 if( !msg->reliable ) {
754 SV_OldClientRemoveMessage( client, msg );
755 }
756
757 }
758
759 SV_OldClientWriteReliableMessages( client, client->netchan->maxpacketlen -
760 msg_write.cursize );
761
762 // send the datagram
763 cursize = client->netchan->Transmit( client->netchan, msg_write.cursize,
764 msg_write.data );
765
766 // record the size for rate estimation
767 SV_CalcSendTime( client, cursize );
768
769 SZ_Clear( &msg_write );
770
771 }
772
SV_OldClientAddUnicast(client_t * client,int clientNum)773 void SV_OldClientAddUnicast( client_t *client, int clientNum ) {
774 qboolean reliable = ( clientNum >> 7 ) & 1;
775 byte data[MAX_PACKETLEN];
776 sizebuf_t buf;
777
778 SZ_Init( &buf, data, sizeof( data ) );
779
780 SZ_WriteByte( &buf, svc_unicast );
781 SZ_WriteByte( &buf, clientNum );
782 SZ_WriteShort( &buf, msg_write.cursize );
783 SZ_Write( &buf, msg_write.data, msg_write.cursize );
784
785 SV_OldClientAddMessage( client, buf.data, buf.cursize, reliable );
786
787 }
788
SV_OldClientAddMulticast(client_t * client,const vec3_t origin,multicast_t to)789 void SV_OldClientAddMulticast( client_t *client, const vec3_t origin,
790 multicast_t to )
791 {
792 qboolean reliable = to >= MULTICAST_ALL_R ? qtrue : qfalse;
793 byte data[MAX_PACKETLEN];
794 sizebuf_t buf;
795 int size;
796
797 SZ_Init( &buf, data, sizeof( data ) );
798
799 size = ( to << 12 ) | ( msg_write.cursize & 0xFFF );
800
801 SZ_WriteByte( &buf, svc_multicast );
802 SZ_WriteShort( &buf, size );
803
804 /* write exact position for PVS/PHS checks */
805 if( to != MULTICAST_ALL && to != MULTICAST_ALL_R ) {
806 SZ_WriteExactPos( &buf, origin );
807 }
808
809 SZ_Write( &buf, msg_write.data, msg_write.cursize );
810
811 SV_OldClientAddMessage( client, buf.data, buf.cursize, reliable );
812 }
813
814
815 /*
816 ===============================================================================
817
818 FRAME UPDATES - Q2PRO CLIENTS
819
820 ===============================================================================
821 */
822
SV_NewClientAddMessage(client_t * client,byte * data,int length,qboolean reliable)823 void SV_NewClientAddMessage( client_t *client, byte *data,
824 int length, qboolean reliable )
825 {
826 sizebuf_t *buf = reliable ? &client->netchan->message : &client->datagram;
827 SZ_Write( buf, data, length );
828 }
829
SV_NewClientWriteDatagram(client_t * client)830 void SV_NewClientWriteDatagram( client_t *client ) {
831 int cursize;
832 int i;
833
834 // send over all the relevant entity_state_t
835 // and the player_state_t
836 client->WriteFrame( client );
837
838 if( msg_write.overflowed ) {
839 // should never happen
840 Com_WPrintf( "Frame overflowed for %s\n", client->name );
841 SZ_Clear( &msg_write );
842 }
843
844 // copy the accumulated multicast datagram
845 // for this client out to the message
846 // it is necessary for this to be after the WriteEntities
847 // so that entity references will be current
848 if( client->datagram.overflowed ) {
849 Com_WPrintf( "Datagram overflowed for %s\n", client->name );
850 } else if( msg_write.cursize + client->datagram.cursize >
851 msg_write.maxsize )
852 {
853 Com_WPrintf( "Dumping datagram for %s\n", client->name );
854 } else {
855 MSG_WriteData( client->datagram.data, client->datagram.cursize );
856 }
857
858 SZ_Clear( &client->datagram );
859
860 if( sv_pad_packets->integer ) {
861 int pad = msg_write.cursize + sv_pad_packets->integer;
862
863 if( pad > msg_write.maxsize ) {
864 pad = msg_write.maxsize;
865 }
866 for( i = msg_write.cursize; i < pad; i++ ) {
867 MSG_WriteByte( svc_nop );
868 }
869 }
870
871 // send the datagram
872 cursize = client->netchan->Transmit( client->netchan, msg_write.cursize,
873 msg_write.data );
874
875 // record the size for rate estimation
876 SV_CalcSendTime( client, cursize );
877
878 // clear the write buffer
879 SZ_Clear( &msg_write );
880 }
881
SV_NewClientAddUnicast(client_t * client,int clientNum)882 void SV_NewClientAddUnicast( client_t *client, int clientNum ) {
883 sizebuf_t *buf;
884
885 if( ( clientNum >> 7 ) & 1 ) {
886 buf = &client->netchan->message;
887 } else {
888 buf = &client->datagram;
889 }
890
891 SZ_WriteByte( buf, svc_unicast );
892 SZ_WriteByte( buf, clientNum );
893 SZ_WriteShort( buf, msg_write.cursize );
894 SZ_Write( buf, msg_write.data, msg_write.cursize );
895 }
896
SV_NewClientAddMulticast(client_t * client,const vec3_t origin,multicast_t to)897 void SV_NewClientAddMulticast( client_t *client, const vec3_t origin,
898 multicast_t to )
899 {
900 int size;
901 sizebuf_t *buf;
902
903 if( to >= MULTICAST_ALL_R ) {
904 buf = &client->netchan->message;
905 } else {
906 buf = &client->datagram;
907 }
908
909 size = ( to << 12 ) | ( msg_write.cursize & 0xFFF );
910
911 SZ_WriteByte( buf, svc_multicast );
912 SZ_WriteShort( buf, size );
913
914 /* write exact position for PVS/PHS checks */
915 if( to != MULTICAST_ALL && to != MULTICAST_ALL_R ) {
916 SZ_WriteExactPos( buf, origin );
917 }
918
919 SZ_Write( buf, msg_write.data, msg_write.cursize );
920 }
921
922 /*
923 ===============================================================================
924
925 COMMON STUFF
926
927 ===============================================================================
928 */
929
930 /*
931 ==================
932 SV_DemoCompleted
933 ==================
934 */
SV_DemoCompleted(void)935 void SV_DemoCompleted( void ) {
936 Com_DPrintf( "SV_DemoCompleted()\n" );
937 if( sv.demofile ) {
938 FS_FCloseFile( sv.demofile );
939 sv.demofile = 0;
940 }
941 SV_Nextserver();
942 }
943
944
945 /*
946 =======================
947 SV_SendClientMessages
948
949 Called each game frame, sends svc_frame messages to spawned clients only.
950 Clients in earlier connection state are handled in SV_SendAsyncPackets.
951 =======================
952 */
SV_SendClientMessages(void)953 void SV_SendClientMessages( void ) {
954 client_t *client;
955 int msglen;
956 int r;
957
958 demo_msglen = 0;
959
960 // read the next demo message if needed
961 if( sv.state == ss_demo && sv.demofile ) {
962 // get the next message
963 r = FS_Read( &msglen, 4, sv.demofile );
964 if( r != 4 ) {
965 SV_DemoCompleted();
966 return;
967 }
968 msglen = LittleLong( msglen );
969 if( msglen == -1 ) {
970 SV_DemoCompleted();
971 return;
972 }
973 if( msglen < 0 || msglen > MAX_PACKETLEN )
974 Com_Error( ERR_DROP, "SV_SendClientMessages: bad demo msglen" );
975 r = FS_Read( demo_data, msglen, sv.demofile );
976 if( r != msglen ) {
977 SV_DemoCompleted();
978 return;
979 }
980 demo_msglen = msglen;
981
982 }
983
984 if( sv.state != ss_game && sv.state != ss_broadcast ) {
985 // send a demo message to each connected client
986 FOR_EACH_CLIENT( client ) {
987 if( client->netchan->type == NETCHAN_OLD ) {
988 SV_OldClientWriteReliableMessages( client,
989 client->netchan->maxpacketlen );
990 }
991 client->netchan->Transmit( client->netchan,
992 demo_msglen, demo_data );
993 }
994 return;
995 }
996
997 // send a message to each connected client
998 FOR_EACH_CLIENT( client ) {
999 if( client->state != cs_spawned || client->download || client->nodata )
1000 continue;
1001
1002 // if the reliable message overflowed,
1003 // drop the client (should never happen)
1004 if( client->netchan->message.overflowed ) {
1005 SZ_Clear( &client->netchan->message );
1006 SV_DropClient( client, "overflowed" );
1007 }
1008
1009 // don't overrun bandwidth
1010 if( SV_RateDrop( client ) ) {
1011 if( sv_debug_send->integer ) {
1012 Com_Printf( "Frame %d surpressed for %s\n", sv.framenum,
1013 client->name );
1014 }
1015 client->surpressCount++;
1016 continue;
1017 }
1018
1019 // don't write any frame data until all fragments are sent
1020 if( client->netchan->fragment_pending ) {
1021 msglen = client->netchan->TransmitNextFragment( client->netchan );
1022 SV_CalcSendTime( client, msglen );
1023 continue;
1024 }
1025
1026 client->BuildFrame( client );
1027 client->WriteDatagram( client );
1028 }
1029 }
1030
1031