1 /*
2 ===========================================================================
3
4 Return to Castle Wolfenstein multiplayer GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (RTCW MP Source Code).
8
9 RTCW MP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 RTCW MP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with RTCW MP Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the RTCW MP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW MP Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29 // cl_parse.c -- parse a message received from the server
30
31 #include "client.h"
32
33 char *svc_strings[256] = {
34 "svc_bad",
35
36 "svc_nop",
37 "svc_gamestate",
38 "svc_configstring",
39 "svc_baseline",
40 "svc_serverCommand",
41 "svc_download",
42 "svc_snapshot",
43 "svc_EOF",
44 "svc_voipSpeex",
45 "svc_voipOpus",
46 };
47
SHOWNET(msg_t * msg,char * s)48 void SHOWNET( msg_t *msg, char *s ) {
49 if ( cl_shownet->integer >= 2 ) {
50 Com_Printf( "%3i:%s\n", msg->readcount - 1, s );
51 }
52 }
53
54
55 /*
56 =========================================================================
57
58 MESSAGE PARSING
59
60 =========================================================================
61 */
62 #if 1
63
64 int entLastVisible[MAX_CLIENTS];
65
isEntVisible(entityState_t * ent)66 qboolean isEntVisible( entityState_t *ent ) {
67 trace_t tr;
68 vec3_t start, end, temp;
69 vec3_t forward, up, right, right2;
70 float view_height;
71
72 VectorCopy( cl.cgameClientLerpOrigin, start );
73 start[2] += ( cl.snap.ps.viewheight - 1 );
74 if ( cl.snap.ps.leanf != 0 ) {
75 vec3_t lright, v3ViewAngles;
76 VectorCopy( cl.snap.ps.viewangles, v3ViewAngles );
77 v3ViewAngles[2] += cl.snap.ps.leanf / 2.0f;
78 AngleVectors( v3ViewAngles, NULL, lright, NULL );
79 VectorMA( start, cl.snap.ps.leanf, lright, start );
80 }
81
82 VectorCopy( ent->pos.trBase, end );
83
84 // Compute vector perpindicular to view to ent
85 VectorSubtract( end, start, forward );
86 VectorNormalizeFast( forward );
87 VectorSet( up, 0, 0, 1 );
88 CrossProduct( forward, up, right );
89 VectorNormalizeFast( right );
90 VectorScale( right, 10, right2 );
91 VectorScale( right, 18, right );
92
93 // Set viewheight
94 if ( ent->animMovetype ) {
95 view_height = 16;
96 } else {
97 view_height = 40;
98 }
99
100 // First, viewpoint to viewpoint
101 end[2] += view_height;
102 CM_BoxTrace( &tr, start, end, NULL, NULL, 0, CONTENTS_SOLID, qfalse );
103 if ( tr.fraction == 1.f ) {
104 return qtrue;
105 }
106
107 // First-b, viewpoint to top of head
108 end[2] += 16;
109 CM_BoxTrace( &tr, start, end, NULL, NULL, 0, CONTENTS_SOLID, qfalse );
110 if ( tr.fraction == 1.f ) {
111 return qtrue;
112 }
113 end[2] -= 16;
114
115 // Second, viewpoint to ent's origin
116 end[2] -= view_height;
117 CM_BoxTrace( &tr, start, end, NULL, NULL, 0, CONTENTS_SOLID, qfalse );
118 if ( tr.fraction == 1.f ) {
119 return qtrue;
120 }
121
122 // Third, to ent's right knee
123 VectorAdd( end, right, temp );
124 temp[2] += 8;
125 CM_BoxTrace( &tr, start, temp, NULL, NULL, 0, CONTENTS_SOLID, qfalse );
126 if ( tr.fraction == 1.f ) {
127 return qtrue;
128 }
129
130 // Fourth, to ent's right shoulder
131 VectorAdd( end, right2, temp );
132 if ( ent->animMovetype ) {
133 temp[2] += 28;
134 } else {
135 temp[2] += 52;
136 }
137 CM_BoxTrace( &tr, start, temp, NULL, NULL, 0, CONTENTS_SOLID, qfalse );
138 if ( tr.fraction == 1.f ) {
139 return qtrue;
140 }
141
142 // Fifth, to ent's left knee
143 VectorScale( right, -1, right );
144 VectorScale( right2, -1, right2 );
145 VectorAdd( end, right2, temp );
146 temp[2] += 2;
147 CM_BoxTrace( &tr, start, temp, NULL, NULL, 0, CONTENTS_SOLID, qfalse );
148 if ( tr.fraction == 1.f ) {
149 return qtrue;
150 }
151
152 // Sixth, to ent's left shoulder
153 VectorAdd( end, right, temp );
154 if ( ent->animMovetype ) {
155 temp[2] += 16;
156 } else {
157 temp[2] += 36;
158 }
159 CM_BoxTrace( &tr, start, temp, NULL, NULL, 0, CONTENTS_SOLID, qfalse );
160 if ( tr.fraction == 1.f ) {
161 return qtrue;
162 }
163
164 return qfalse;
165 }
166
167 #endif
168
169 /*
170 ==================
171 CL_DeltaEntity
172
173 Parses deltas from the given base and adds the resulting entity
174 to the current frame
175 ==================
176 */
CL_DeltaEntity(msg_t * msg,clSnapshot_t * frame,int newnum,entityState_t * old,qboolean unchanged)177 void CL_DeltaEntity( msg_t *msg, clSnapshot_t *frame, int newnum, entityState_t *old,
178 qboolean unchanged ) {
179 entityState_t *state;
180
181 // save the parsed entity state into the big circular buffer so
182 // it can be used as the source for a later delta
183 state = &cl.parseEntities[cl.parseEntitiesNum & ( MAX_PARSE_ENTITIES - 1 )];
184
185 if ( unchanged ) {
186 *state = *old;
187 } else {
188 MSG_ReadDeltaEntity( msg, old, state, newnum );
189 }
190
191 if ( state->number == ( MAX_GENTITIES - 1 ) ) {
192 return; // entity was delta removed
193 }
194
195 #if 1
196 // DHM - Nerve :: Only draw clients if visible
197 if ( clc.onlyVisibleClients ) {
198 if ( state->number < MAX_CLIENTS ) {
199 if ( isEntVisible( state ) ) {
200 entLastVisible[state->number] = frame->serverTime;
201 state->eFlags &= ~EF_NODRAW;
202 } else {
203 if ( entLastVisible[state->number] < ( frame->serverTime - 600 ) ) {
204 state->eFlags |= EF_NODRAW;
205 }
206 }
207 }
208 }
209 #endif
210
211 cl.parseEntitiesNum++;
212 frame->numEntities++;
213 }
214
215 /*
216 ==================
217 CL_ParsePacketEntities
218
219 ==================
220 */
CL_ParsePacketEntities(msg_t * msg,clSnapshot_t * oldframe,clSnapshot_t * newframe)221 void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *newframe ) {
222 int newnum;
223 entityState_t *oldstate;
224 int oldindex, oldnum;
225
226 newframe->parseEntitiesNum = cl.parseEntitiesNum;
227 newframe->numEntities = 0;
228
229 // delta from the entities present in oldframe
230 oldindex = 0;
231 oldstate = NULL;
232 if ( !oldframe ) {
233 oldnum = 99999;
234 } else {
235 if ( oldindex >= oldframe->numEntities ) {
236 oldnum = 99999;
237 } else {
238 oldstate = &cl.parseEntities[
239 ( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 )];
240 oldnum = oldstate->number;
241 }
242 }
243
244 while ( 1 ) {
245 // read the entity index number
246 newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
247
248 if ( newnum == ( MAX_GENTITIES - 1 ) ) {
249 break;
250 }
251
252 if ( msg->readcount > msg->cursize ) {
253 Com_Error( ERR_DROP,"CL_ParsePacketEntities: end of message" );
254 }
255
256 while ( oldnum < newnum ) {
257 // one or more entities from the old packet are unchanged
258 if ( cl_shownet->integer == 3 ) {
259 Com_Printf( "%3i: unchanged: %i\n", msg->readcount, oldnum );
260 }
261 CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );
262
263 oldindex++;
264
265 if ( oldindex >= oldframe->numEntities ) {
266 oldnum = 99999;
267 } else {
268 oldstate = &cl.parseEntities[
269 ( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 )];
270 oldnum = oldstate->number;
271 }
272 }
273 if ( oldnum == newnum ) {
274 // delta from previous state
275 if ( cl_shownet->integer == 3 ) {
276 Com_Printf( "%3i: delta: %i\n", msg->readcount, newnum );
277 }
278 CL_DeltaEntity( msg, newframe, newnum, oldstate, qfalse );
279
280 oldindex++;
281
282 if ( oldindex >= oldframe->numEntities ) {
283 oldnum = 99999;
284 } else {
285 oldstate = &cl.parseEntities[
286 ( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 )];
287 oldnum = oldstate->number;
288 }
289 continue;
290 }
291
292 if ( oldnum > newnum ) {
293 // delta from baseline
294 if ( cl_shownet->integer == 3 ) {
295 Com_Printf( "%3i: baseline: %i\n", msg->readcount, newnum );
296 }
297 CL_DeltaEntity( msg, newframe, newnum, &cl.entityBaselines[newnum], qfalse );
298 continue;
299 }
300
301 }
302
303 // any remaining entities in the old frame are copied over
304 while ( oldnum != 99999 ) {
305 // one or more entities from the old packet are unchanged
306 if ( cl_shownet->integer == 3 ) {
307 Com_Printf( "%3i: unchanged: %i\n", msg->readcount, oldnum );
308 }
309 CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );
310
311 oldindex++;
312
313 if ( oldindex >= oldframe->numEntities ) {
314 oldnum = 99999;
315 } else {
316 oldstate = &cl.parseEntities[
317 ( oldframe->parseEntitiesNum + oldindex ) & ( MAX_PARSE_ENTITIES - 1 )];
318 oldnum = oldstate->number;
319 }
320 }
321
322 if ( cl_shownuments->integer ) {
323 Com_Printf( "Entities in packet: %i\n", newframe->numEntities );
324 }
325 }
326
327
328 /*
329 ================
330 CL_ParseSnapshot
331
332 If the snapshot is parsed properly, it will be copied to
333 cl.snap and saved in cl.snapshots[]. If the snapshot is invalid
334 for any reason, no changes to the state will be made at all.
335 ================
336 */
CL_ParseSnapshot(msg_t * msg)337 void CL_ParseSnapshot( msg_t *msg ) {
338 int len;
339 clSnapshot_t *old;
340 clSnapshot_t newSnap;
341 int deltaNum;
342 int oldMessageNum;
343 int i, packetNum;
344
345 // get the reliable sequence acknowledge number
346 // NOTE: now sent with all server to client messages
347 //clc.reliableAcknowledge = MSG_ReadLong( msg );
348
349 // read in the new snapshot to a temporary buffer
350 // we will only copy to cl.snap if it is valid
351 memset( &newSnap, 0, sizeof( newSnap ) );
352
353 // we will have read any new server commands in this
354 // message before we got to svc_snapshot
355 newSnap.serverCommandNum = clc.serverCommandSequence;
356
357 newSnap.serverTime = MSG_ReadLong( msg );
358
359 // if we were just unpaused, we can only *now* really let the
360 // change come into effect or the client hangs.
361 cl_paused->modified = 0;
362
363 newSnap.messageNum = clc.serverMessageSequence;
364
365 deltaNum = MSG_ReadByte( msg );
366 if ( !deltaNum ) {
367 newSnap.deltaNum = -1;
368 } else {
369 newSnap.deltaNum = newSnap.messageNum - deltaNum;
370 }
371 newSnap.snapFlags = MSG_ReadByte( msg );
372
373 // If the frame is delta compressed from data that we
374 // no longer have available, we must suck up the rest of
375 // the frame, but not use it, then ask for a non-compressed
376 // message
377 if ( newSnap.deltaNum <= 0 ) {
378 newSnap.valid = qtrue; // uncompressed frame
379 old = NULL;
380 clc.demowaiting = qfalse; // we can start recording now
381 } else {
382 old = &cl.snapshots[newSnap.deltaNum & PACKET_MASK];
383 if ( !old->valid ) {
384 // should never happen
385 Com_Printf( "Delta from invalid frame (not supposed to happen!).\n" );
386 } else if ( old->messageNum != newSnap.deltaNum ) {
387 // The frame that the server did the delta from
388 // is too old, so we can't reconstruct it properly.
389 Com_DPrintf( "Delta frame too old.\n" );
390 } else if ( cl.parseEntitiesNum - old->parseEntitiesNum > MAX_PARSE_ENTITIES - MAX_SNAPSHOT_ENTITIES ) {
391 Com_DPrintf( "Delta parseEntitiesNum too old.\n" );
392 } else {
393 newSnap.valid = qtrue; // valid delta parse
394 }
395 }
396
397 // read areamask
398 len = MSG_ReadByte( msg );
399
400 if ( len > sizeof( newSnap.areamask ) ) {
401 Com_Error( ERR_DROP,"CL_ParseSnapshot: Invalid size %d for areamask.", len );
402 return;
403 }
404
405 MSG_ReadData( msg, &newSnap.areamask, len );
406
407 // read playerinfo
408 SHOWNET( msg, "playerstate" );
409 if ( old ) {
410 MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps );
411 } else {
412 MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps );
413 }
414
415 // read packet entities
416 SHOWNET( msg, "packet entities" );
417 CL_ParsePacketEntities( msg, old, &newSnap );
418
419 // if not valid, dump the entire thing now that it has
420 // been properly read
421 if ( !newSnap.valid ) {
422 return;
423 }
424
425 // clear the valid flags of any snapshots between the last
426 // received and this one, so if there was a dropped packet
427 // it won't look like something valid to delta from next
428 // time we wrap around in the buffer
429 oldMessageNum = cl.snap.messageNum + 1;
430
431 if ( newSnap.messageNum - oldMessageNum >= PACKET_BACKUP ) {
432 oldMessageNum = newSnap.messageNum - ( PACKET_BACKUP - 1 );
433 }
434 for ( ; oldMessageNum < newSnap.messageNum ; oldMessageNum++ ) {
435 cl.snapshots[oldMessageNum & PACKET_MASK].valid = qfalse;
436 }
437
438 // copy to the current good spot
439 cl.snap = newSnap;
440 cl.snap.ping = 999;
441 // calculate ping time
442 for ( i = 0 ; i < PACKET_BACKUP ; i++ ) {
443 packetNum = ( clc.netchan.outgoingSequence - 1 - i ) & PACKET_MASK;
444 if ( cl.snap.ps.commandTime >= cl.outPackets[ packetNum ].p_serverTime ) {
445 cl.snap.ping = cls.realtime - cl.outPackets[ packetNum ].p_realtime;
446 break;
447 }
448 }
449 // save the frame off in the backup array for later delta comparisons
450 cl.snapshots[cl.snap.messageNum & PACKET_MASK] = cl.snap;
451
452 if ( cl_shownet->integer == 3 ) {
453 Com_Printf( " snapshot:%i delta:%i ping:%i\n", cl.snap.messageNum,
454 cl.snap.deltaNum, cl.snap.ping );
455 }
456
457 cl.newSnapshots = qtrue;
458 }
459
460
461 //=====================================================================
462
463 int cl_connectedToPureServer;
464 int cl_connectedToCheatServer;
465
466 /*
467 ==================
468 CL_SystemInfoChanged
469
470 The systeminfo configstring has been changed, so parse
471 new information out of it. This will happen at every
472 gamestate, and possibly during gameplay.
473 ==================
474 */
CL_SystemInfoChanged(void)475 void CL_SystemInfoChanged( void ) {
476 char *systemInfo;
477 const char *s, *t;
478 char key[BIG_INFO_KEY];
479 char value[BIG_INFO_VALUE];
480 qboolean gameSet;
481
482 systemInfo = cl.gameState.stringData + cl.gameState.stringOffsets[ CS_SYSTEMINFO ];
483 cl.serverId = atoi( Info_ValueForKey( systemInfo, "sv_serverid" ) );
484
485 memset( &entLastVisible, 0, sizeof( entLastVisible ) );
486
487 #ifdef USE_VOIP
488 #ifdef LEGACY_PROTOCOL
489 if(clc.compat)
490 clc.voipEnabled = qfalse;
491 else
492 #endif
493 {
494 s = Info_ValueForKey( systemInfo, "sv_voipProtocol" );
495 clc.voipEnabled = !Q_stricmp(s, "opus");
496 }
497 #endif
498
499 // don't set any vars when playing a demo
500 if ( clc.demoplaying ) {
501 return;
502 }
503
504 s = Info_ValueForKey( systemInfo, "sv_cheats" );
505 cl_connectedToCheatServer = atoi( s );
506 if ( !cl_connectedToCheatServer ) {
507 Cvar_SetCheatState();
508 }
509
510 // check pure server string
511 s = Info_ValueForKey( systemInfo, "sv_paks" );
512 t = Info_ValueForKey( systemInfo, "sv_pakNames" );
513 FS_PureServerSetLoadedPaks( s, t );
514
515 s = Info_ValueForKey( systemInfo, "sv_referencedPaks" );
516 t = Info_ValueForKey( systemInfo, "sv_referencedPakNames" );
517 FS_PureServerSetReferencedPaks( s, t );
518
519 gameSet = qfalse;
520 // scan through all the variables in the systeminfo and locally set cvars to match
521 s = systemInfo;
522 while ( s ) {
523 int cvar_flags;
524
525 Info_NextPair( &s, key, value );
526 if ( !key[0] ) {
527 break;
528 }
529
530 // ehw!
531 if (!Q_stricmp(key, "fs_game"))
532 {
533 if(FS_InvalidGameDir(value))
534 {
535 Com_Printf(S_COLOR_YELLOW "WARNING: Server sent invalid fs_game value %s\n", value);
536 continue;
537 }
538
539 gameSet = qtrue;
540 }
541
542 if((cvar_flags = Cvar_Flags(key)) == CVAR_NONEXISTENT)
543 Cvar_Get(key, value, CVAR_SERVER_CREATED | CVAR_ROM);
544 else
545 {
546 // If this cvar may not be modified by a server discard the value.
547 if(!(cvar_flags & (CVAR_SYSTEMINFO | CVAR_SERVER_CREATED | CVAR_USER_CREATED)))
548 {
549 #ifndef STANDALONE
550 if(Q_stricmp(key, "g_synchronousClients") && Q_stricmp(key, "pmove_fixed") &&
551 Q_stricmp(key, "pmove_msec"))
552 #endif
553 {
554 Com_DPrintf(S_COLOR_YELLOW "WARNING: server is not allowed to set %s=%s\n", key, value);
555 continue;
556 }
557 }
558
559 Cvar_SetSafe(key, value);
560 }
561 }
562 // if game folder should not be set and it is set at the client side
563 if ( !gameSet && *Cvar_VariableString("fs_game") ) {
564 Cvar_Set( "fs_game", "" );
565 }
566 cl_connectedToPureServer = Cvar_VariableValue( "sv_pure" );
567 }
568
569 /*
570 ==================
571 CL_ParseServerInfo
572 ==================
573 */
CL_ParseServerInfo(void)574 static void CL_ParseServerInfo(void)
575 {
576 const char *serverInfo;
577
578 serverInfo = cl.gameState.stringData
579 + cl.gameState.stringOffsets[ CS_SERVERINFO ];
580
581 clc.sv_allowDownload = atoi(Info_ValueForKey(serverInfo,
582 "sv_allowDownload"));
583 Q_strncpyz(clc.sv_dlURL,
584 Info_ValueForKey(serverInfo, "sv_dlURL"),
585 sizeof(clc.sv_dlURL));
586 }
587
588 /*
589 ==================
590 CL_ParseGamestate
591 ==================
592 */
CL_ParseGamestate(msg_t * msg)593 void CL_ParseGamestate( msg_t *msg ) {
594 int i;
595 entityState_t *es;
596 int newnum;
597 entityState_t nullstate;
598 int cmd;
599 char *s;
600 char oldGame[MAX_QPATH];
601
602 Con_Close();
603
604 clc.connectPacketCount = 0;
605
606 // wipe local client state
607 CL_ClearState();
608
609 // a gamestate always marks a server command sequence
610 clc.serverCommandSequence = MSG_ReadLong( msg );
611
612 // parse all the configstrings and baselines
613 cl.gameState.dataCount = 1; // leave a 0 at the beginning for uninitialized configstrings
614 while ( 1 ) {
615 cmd = MSG_ReadByte( msg );
616
617 if ( cmd == svc_EOF ) {
618 break;
619 }
620
621 if ( cmd == svc_configstring ) {
622 int len;
623
624 i = MSG_ReadShort( msg );
625 if ( i < 0 || i >= MAX_CONFIGSTRINGS ) {
626 Com_Error( ERR_DROP, "configstring > MAX_CONFIGSTRINGS" );
627 }
628 s = MSG_ReadBigString( msg );
629 len = strlen( s );
630
631 if ( len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS ) {
632 Com_Error( ERR_DROP, "MAX_GAMESTATE_CHARS exceeded" );
633 }
634
635 // append it to the gameState string buffer
636 cl.gameState.stringOffsets[ i ] = cl.gameState.dataCount;
637 memcpy( cl.gameState.stringData + cl.gameState.dataCount, s, len + 1 );
638 cl.gameState.dataCount += len + 1;
639 } else if ( cmd == svc_baseline ) {
640 newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
641 if ( newnum < 0 || newnum >= MAX_GENTITIES ) {
642 Com_Error( ERR_DROP, "Baseline number out of range: %i", newnum );
643 }
644 memset( &nullstate, 0, sizeof( nullstate ) );
645 es = &cl.entityBaselines[ newnum ];
646 MSG_ReadDeltaEntity( msg, &nullstate, es, newnum );
647 } else {
648 Com_Error( ERR_DROP, "CL_ParseGamestate: bad command byte" );
649 }
650 }
651
652 clc.clientNum = MSG_ReadLong( msg );
653 // read the checksum feed
654 clc.checksumFeed = MSG_ReadLong( msg );
655
656 // save old gamedir
657 Cvar_VariableStringBuffer("fs_game", oldGame, sizeof(oldGame));
658
659 // parse useful values out of CS_SERVERINFO
660 CL_ParseServerInfo();
661
662 // parse serverId and other cvars
663 CL_SystemInfoChanged();
664
665 // stop recording now so the demo won't have an unnecessary level load at the end.
666 if(cl_autoRecordDemo->integer && clc.demorecording)
667 CL_StopRecord_f();
668
669 // reinitialize the filesystem if the game directory has changed
670 if(!cl_oldGameSet && (Cvar_Flags("fs_game") & CVAR_MODIFIED))
671 {
672 cl_oldGameSet = qtrue;
673 Q_strncpyz(cl_oldGame, oldGame, sizeof(cl_oldGame));
674 }
675
676 FS_ConditionalRestart(clc.checksumFeed, qfalse);
677
678 // This used to call CL_StartHunkUsers, but now we enter the download state before loading the
679 // cgame
680 CL_InitDownloads();
681
682 // make sure the game starts
683 Cvar_Set( "cl_paused", "0" );
684 }
685
686
687 //=====================================================================
688
689 /*
690 =====================
691 CL_ParseDownload
692
693 A download message has been received from the server
694 =====================
695 */
CL_ParseDownload(msg_t * msg)696 void CL_ParseDownload( msg_t *msg ) {
697 int size;
698 unsigned char data[MAX_MSGLEN];
699 uint16_t block;
700
701 if (!*clc.downloadTempName) {
702 Com_Printf("Server sending download, but no download was requested\n");
703 CL_AddReliableCommand("stopdl", qfalse);
704 return;
705 }
706
707 // read the data
708 block = MSG_ReadShort( msg );
709
710 if( !block && !clc.downloadBlock ) {
711 // block zero is special, contains file size
712 clc.downloadSize = MSG_ReadLong( msg );
713
714 Cvar_SetValue( "cl_downloadSize", clc.downloadSize );
715
716 if ( clc.downloadSize < 0 ) {
717 Com_Error( ERR_DROP, "%s", MSG_ReadString( msg ) );
718 return;
719 }
720 }
721
722 size = MSG_ReadShort( msg );
723 if ( size < 0 || size > sizeof( data ) ) {
724 Com_Error( ERR_DROP, "CL_ParseDownload: Invalid size %d for download chunk", size );
725 return;
726 }
727
728 MSG_ReadData( msg, data, size );
729
730 if( ( clc.downloadBlock & 0xFFFF ) != block ) {
731 Com_DPrintf( "CL_ParseDownload: Expected block %d, got %d\n", (clc.downloadBlock & 0xFFFF), block);
732 return;
733 }
734
735 // open the file if not opened yet
736 if ( !clc.download ) {
737 clc.download = FS_SV_FOpenFileWrite( clc.downloadTempName );
738
739 if ( !clc.download ) {
740 Com_Printf( "Could not create %s\n", clc.downloadTempName );
741 CL_AddReliableCommand("stopdl", qfalse);
742 CL_NextDownload();
743 return;
744 }
745 }
746
747 if ( size ) {
748 FS_Write( data, size, clc.download );
749 }
750
751 CL_AddReliableCommand(va("nextdl %d", clc.downloadBlock), qfalse);
752 clc.downloadBlock++;
753
754 clc.downloadCount += size;
755
756 // So UI gets access to it
757 Cvar_SetValue( "cl_downloadCount", clc.downloadCount );
758
759 if ( !size ) { // A zero length block means EOF
760 if ( clc.download ) {
761 FS_FCloseFile( clc.download );
762 clc.download = 0;
763
764 // rename the file
765 FS_SV_Rename( clc.downloadTempName, clc.downloadName, qfalse );
766 }
767
768 // send intentions now
769 // We need this because without it, we would hold the last nextdl and then start
770 // loading right away. If we take a while to load, the server is happily trying
771 // to send us that last block over and over.
772 // Write it twice to help make sure we acknowledge the download
773 CL_WritePacket();
774 CL_WritePacket();
775
776 // get another file if needed
777 CL_NextDownload();
778 }
779 }
780
781 #ifdef USE_VOIP
782 static
CL_ShouldIgnoreVoipSender(int sender)783 qboolean CL_ShouldIgnoreVoipSender(int sender)
784 {
785 if (!cl_voip->integer)
786 return qtrue; // VoIP is disabled.
787 else if ((sender == clc.clientNum) && (!clc.demoplaying))
788 return qtrue; // ignore own voice (unless playing back a demo).
789 else if (clc.voipMuteAll)
790 return qtrue; // all channels are muted with extreme prejudice.
791 else if (clc.voipIgnore[sender])
792 return qtrue; // just ignoring this guy.
793 else if (clc.voipGain[sender] == 0.0f)
794 return qtrue; // too quiet to play.
795
796 return qfalse;
797 }
798
799 /*
800 =====================
801 CL_PlayVoip
802
803 Play raw data
804 =====================
805 */
806
CL_PlayVoip(int sender,int samplecnt,const byte * data,int flags)807 static void CL_PlayVoip(int sender, int samplecnt, const byte *data, int flags)
808 {
809 if(flags & VOIP_DIRECT)
810 {
811 S_RawSamples(sender + 1, samplecnt, 48000, 2, 1,
812 data, clc.voipGain[sender], -1);
813 }
814
815 if(flags & VOIP_SPATIAL)
816 {
817 S_RawSamples(sender + MAX_CLIENTS + 1, samplecnt, 48000, 2, 1,
818 data, 1.0f, sender);
819 }
820 }
821
822 /*
823 =====================
824 CL_ParseVoip
825
826 A VoIP message has been received from the server
827 =====================
828 */
829 static
CL_ParseVoip(msg_t * msg,qboolean ignoreData)830 void CL_ParseVoip ( msg_t *msg, qboolean ignoreData ) {
831 static short decoded[VOIP_MAX_PACKET_SAMPLES*4]; // !!! FIXME: don't hard code
832
833 const int sender = MSG_ReadShort(msg);
834 const int generation = MSG_ReadByte(msg);
835 const int sequence = MSG_ReadLong(msg);
836 const int frames = MSG_ReadByte(msg);
837 const int packetsize = MSG_ReadShort(msg);
838 const int flags = MSG_ReadBits(msg, VOIP_FLAGCNT);
839 unsigned char encoded[4000];
840 int numSamples;
841 int seqdiff;
842 int written = 0;
843 int i;
844
845 Com_DPrintf("VoIP: %d-byte packet from client %d\n", packetsize, sender);
846
847 if (sender < 0)
848 return; // short/invalid packet, bail.
849 else if (generation < 0)
850 return; // short/invalid packet, bail.
851 else if (sequence < 0)
852 return; // short/invalid packet, bail.
853 else if (frames < 0)
854 return; // short/invalid packet, bail.
855 else if (packetsize < 0)
856 return; // short/invalid packet, bail.
857
858 if (packetsize > sizeof (encoded)) { // overlarge packet?
859 int bytesleft = packetsize;
860 while (bytesleft) {
861 int br = bytesleft;
862 if (br > sizeof (encoded))
863 br = sizeof (encoded);
864 MSG_ReadData(msg, encoded, br);
865 bytesleft -= br;
866 }
867 return; // overlarge packet, bail.
868 }
869
870 MSG_ReadData(msg, encoded, packetsize);
871
872 if (ignoreData) {
873 return; // just ignore legacy speex voip data
874 } else if (!clc.voipCodecInitialized) {
875 return; // can't handle VoIP without libopus!
876 } else if (sender >= MAX_CLIENTS) {
877 return; // bogus sender.
878 } else if (CL_ShouldIgnoreVoipSender(sender)) {
879 return; // Channel is muted, bail.
880 }
881
882 // !!! FIXME: make sure data is narrowband? Does decoder handle this?
883
884 Com_DPrintf("VoIP: packet accepted!\n");
885
886 seqdiff = sequence - clc.voipIncomingSequence[sender];
887
888 // This is a new "generation" ... a new recording started, reset the bits.
889 if (generation != clc.voipIncomingGeneration[sender]) {
890 Com_DPrintf("VoIP: new generation %d!\n", generation);
891 opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE);
892 clc.voipIncomingGeneration[sender] = generation;
893 seqdiff = 0;
894 } else if (seqdiff < 0) { // we're ahead of the sequence?!
895 // This shouldn't happen unless the packet is corrupted or something.
896 Com_DPrintf("VoIP: misordered sequence! %d < %d!\n",
897 sequence, clc.voipIncomingSequence[sender]);
898 // reset the decoder just in case.
899 opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE);
900 seqdiff = 0;
901 } else if (seqdiff * VOIP_MAX_PACKET_SAMPLES*2 >= sizeof (decoded)) { // dropped more than we can handle?
902 // just start over.
903 Com_DPrintf("VoIP: Dropped way too many (%d) frames from client #%d\n",
904 seqdiff, sender);
905 opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE);
906 seqdiff = 0;
907 }
908
909 if (seqdiff != 0) {
910 Com_DPrintf("VoIP: Dropped %d frames from client #%d\n",
911 seqdiff, sender);
912 // tell opus that we're missing frames...
913 for (i = 0; i < seqdiff; i++) {
914 assert((written + VOIP_MAX_PACKET_SAMPLES) * 2 < sizeof (decoded));
915 numSamples = opus_decode(clc.opusDecoder[sender], NULL, 0, decoded + written, VOIP_MAX_PACKET_SAMPLES, 0);
916 if ( numSamples <= 0 ) {
917 Com_DPrintf("VoIP: Error decoding frame %d from client #%d\n", i, sender);
918 continue;
919 }
920 written += numSamples;
921 }
922 }
923
924 numSamples = opus_decode(clc.opusDecoder[sender], encoded, packetsize, decoded + written, ARRAY_LEN(decoded) - written, 0);
925
926 if ( numSamples <= 0 ) {
927 Com_DPrintf("VoIP: Error decoding voip data from client #%d\n", sender);
928 numSamples = 0;
929 }
930
931 #if 0
932 static FILE *encio = NULL;
933 if (encio == NULL) encio = fopen("voip-incoming-encoded.bin", "wb");
934 if (encio != NULL) { fwrite(encoded, packetsize, 1, encio); fflush(encio); }
935 static FILE *decio = NULL;
936 if (decio == NULL) decio = fopen("voip-incoming-decoded.bin", "wb");
937 if (decio != NULL) { fwrite(decoded+written, numSamples*2, 1, decio); fflush(decio); }
938 #endif
939
940 written += numSamples;
941
942 Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n",
943 written * 2, written, frames);
944
945 if(written > 0)
946 CL_PlayVoip(sender, written, (const byte *) decoded, flags);
947
948 clc.voipIncomingSequence[sender] = sequence + frames;
949 }
950 #endif
951
952 /*
953 =====================
954 CL_ParseCommandString
955
956 Command strings are just saved off until cgame asks for them
957 when it transitions a snapshot
958 =====================
959 */
CL_ParseCommandString(msg_t * msg)960 void CL_ParseCommandString( msg_t *msg ) {
961 char *s;
962 int seq;
963 int index;
964
965 seq = MSG_ReadLong( msg );
966 s = MSG_ReadString( msg );
967
968 // see if we have already executed stored it off
969 if ( clc.serverCommandSequence >= seq ) {
970 return;
971 }
972 clc.serverCommandSequence = seq;
973
974 index = seq & ( MAX_RELIABLE_COMMANDS - 1 );
975 Q_strncpyz( clc.serverCommands[ index ], s, sizeof( clc.serverCommands[ index ] ) );
976 }
977
978
979 /*
980 =====================
981 CL_ParseServerMessage
982 =====================
983 */
CL_ParseServerMessage(msg_t * msg)984 void CL_ParseServerMessage( msg_t *msg ) {
985 int cmd;
986
987 if ( cl_shownet->integer == 1 ) {
988 Com_Printf( "%i ",msg->cursize );
989 } else if ( cl_shownet->integer >= 2 ) {
990 Com_Printf( "------------------\n" );
991 }
992
993 MSG_Bitstream( msg );
994
995 // get the reliable sequence acknowledge number
996 clc.reliableAcknowledge = MSG_ReadLong( msg );
997 //
998 if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS ) {
999 clc.reliableAcknowledge = clc.reliableSequence;
1000 }
1001
1002 //
1003 // parse the message
1004 //
1005 while ( 1 ) {
1006 if ( msg->readcount > msg->cursize ) {
1007 Com_Error( ERR_DROP,"CL_ParseServerMessage: read past end of server message" );
1008 break;
1009 }
1010
1011 cmd = MSG_ReadByte( msg );
1012
1013 if ( cmd == svc_EOF ) {
1014 SHOWNET( msg, "END OF MESSAGE" );
1015 break;
1016 }
1017
1018 if ( cl_shownet->integer >= 2 ) {
1019 if ( (cmd < 0) || (!svc_strings[cmd]) ) {
1020 Com_Printf( "%3i:BAD CMD %i\n", msg->readcount - 1, cmd );
1021 } else {
1022 SHOWNET( msg, svc_strings[cmd] );
1023 }
1024 }
1025
1026 // other commands
1027 switch ( cmd ) {
1028 default:
1029 Com_Error (ERR_DROP,"CL_ParseServerMessage: Illegible server message");
1030 break;
1031 case svc_nop:
1032 break;
1033 case svc_serverCommand:
1034 CL_ParseCommandString( msg );
1035 break;
1036 case svc_gamestate:
1037 CL_ParseGamestate( msg );
1038 break;
1039 case svc_snapshot:
1040 CL_ParseSnapshot( msg );
1041 break;
1042 case svc_download:
1043 CL_ParseDownload( msg );
1044 break;
1045 case svc_voipSpeex:
1046 #ifdef USE_VOIP
1047 CL_ParseVoip( msg, qtrue );
1048 #endif
1049 break;
1050 case svc_voipOpus:
1051 #ifdef USE_VOIP
1052 CL_ParseVoip( msg, !clc.voipEnabled );
1053 #endif
1054 break;
1055 }
1056 }
1057 }
1058