00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "client.h"
00025
00026 char *svc_strings[256] = {
00027 "svc_bad",
00028
00029 "svc_nop",
00030 "svc_gamestate",
00031 "svc_configstring",
00032 "svc_baseline",
00033 "svc_serverCommand",
00034 "svc_download",
00035 "svc_snapshot"
00036 };
00037
00038 void SHOWNET( msg_t *msg, char *s) {
00039 if ( cl_shownet->integer >= 2) {
00040 Com_Printf ("%3i:%s\n", msg->readcount-1, s);
00041 }
00042 }
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 void CL_DeltaEntity (msg_t *msg, clSnapshot_t *frame, int newnum, entityState_t *old,
00062 qboolean unchanged) {
00063 entityState_t *state;
00064
00065
00066
00067 state = &cl.parseEntities[cl.parseEntitiesNum & (MAX_PARSE_ENTITIES-1)];
00068
00069 if ( unchanged ) {
00070 *state = *old;
00071 } else {
00072 MSG_ReadDeltaEntity( msg, old, state, newnum );
00073 }
00074
00075 if ( state->number == (MAX_GENTITIES-1) ) {
00076 return;
00077 }
00078 cl.parseEntitiesNum++;
00079 frame->numEntities++;
00080 }
00081
00082
00083
00084
00085
00086
00087
00088 void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *newframe) {
00089 int newnum;
00090 entityState_t *oldstate;
00091 int oldindex, oldnum;
00092
00093 newframe->parseEntitiesNum = cl.parseEntitiesNum;
00094 newframe->numEntities = 0;
00095
00096
00097 oldindex = 0;
00098 oldstate = NULL;
00099 if (!oldframe) {
00100 oldnum = 99999;
00101 } else {
00102 if ( oldindex >= oldframe->numEntities ) {
00103 oldnum = 99999;
00104 } else {
00105 oldstate = &cl.parseEntities[
00106 (oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
00107 oldnum = oldstate->number;
00108 }
00109 }
00110
00111 while ( 1 ) {
00112
00113 newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
00114
00115 if ( newnum == (MAX_GENTITIES-1) ) {
00116 break;
00117 }
00118
00119 if ( msg->readcount > msg->cursize ) {
00120 Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");
00121 }
00122
00123 while ( oldnum < newnum ) {
00124
00125 if ( cl_shownet->integer == 3 ) {
00126 Com_Printf ("%3i: unchanged: %i\n", msg->readcount, oldnum);
00127 }
00128 CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );
00129
00130 oldindex++;
00131
00132 if ( oldindex >= oldframe->numEntities ) {
00133 oldnum = 99999;
00134 } else {
00135 oldstate = &cl.parseEntities[
00136 (oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
00137 oldnum = oldstate->number;
00138 }
00139 }
00140 if (oldnum == newnum) {
00141
00142 if ( cl_shownet->integer == 3 ) {
00143 Com_Printf ("%3i: delta: %i\n", msg->readcount, newnum);
00144 }
00145 CL_DeltaEntity( msg, newframe, newnum, oldstate, qfalse );
00146
00147 oldindex++;
00148
00149 if ( oldindex >= oldframe->numEntities ) {
00150 oldnum = 99999;
00151 } else {
00152 oldstate = &cl.parseEntities[
00153 (oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
00154 oldnum = oldstate->number;
00155 }
00156 continue;
00157 }
00158
00159 if ( oldnum > newnum ) {
00160
00161 if ( cl_shownet->integer == 3 ) {
00162 Com_Printf ("%3i: baseline: %i\n", msg->readcount, newnum);
00163 }
00164 CL_DeltaEntity( msg, newframe, newnum, &cl.entityBaselines[newnum], qfalse );
00165 continue;
00166 }
00167
00168 }
00169
00170
00171 while ( oldnum != 99999 ) {
00172
00173 if ( cl_shownet->integer == 3 ) {
00174 Com_Printf ("%3i: unchanged: %i\n", msg->readcount, oldnum);
00175 }
00176 CL_DeltaEntity( msg, newframe, oldnum, oldstate, qtrue );
00177
00178 oldindex++;
00179
00180 if ( oldindex >= oldframe->numEntities ) {
00181 oldnum = 99999;
00182 } else {
00183 oldstate = &cl.parseEntities[
00184 (oldframe->parseEntitiesNum + oldindex) & (MAX_PARSE_ENTITIES-1)];
00185 oldnum = oldstate->number;
00186 }
00187 }
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 void CL_ParseSnapshot( msg_t *msg ) {
00201 int len;
00202 clSnapshot_t *old;
00203 clSnapshot_t newSnap;
00204 int deltaNum;
00205 int oldMessageNum;
00206 int i, packetNum;
00207
00208
00209
00210
00211
00212
00213
00214 Com_Memset (&newSnap, 0, sizeof(newSnap));
00215
00216
00217
00218 newSnap.serverCommandNum = clc.serverCommandSequence;
00219
00220 newSnap.serverTime = MSG_ReadLong( msg );
00221
00222 newSnap.messageNum = clc.serverMessageSequence;
00223
00224 deltaNum = MSG_ReadByte( msg );
00225 if ( !deltaNum ) {
00226 newSnap.deltaNum = -1;
00227 } else {
00228 newSnap.deltaNum = newSnap.messageNum - deltaNum;
00229 }
00230 newSnap.snapFlags = MSG_ReadByte( msg );
00231
00232
00233
00234
00235
00236 if ( newSnap.deltaNum <= 0 ) {
00237 newSnap.valid = qtrue;
00238 old = NULL;
00239 clc.demowaiting = qfalse;
00240 } else {
00241 old = &cl.snapshots[newSnap.deltaNum & PACKET_MASK];
00242 if ( !old->valid ) {
00243
00244 Com_Printf ("Delta from invalid frame (not supposed to happen!).\n");
00245 } else if ( old->messageNum != newSnap.deltaNum ) {
00246
00247
00248 Com_Printf ("Delta frame too old.\n");
00249 } else if ( cl.parseEntitiesNum - old->parseEntitiesNum > MAX_PARSE_ENTITIES-128 ) {
00250 Com_Printf ("Delta parseEntitiesNum too old.\n");
00251 } else {
00252 newSnap.valid = qtrue;
00253 }
00254 }
00255
00256
00257 len = MSG_ReadByte( msg );
00258 MSG_ReadData( msg, &newSnap.areamask, len);
00259
00260
00261 SHOWNET( msg, "playerstate" );
00262 if ( old ) {
00263 MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps );
00264 } else {
00265 MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps );
00266 }
00267
00268
00269 SHOWNET( msg, "packet entities" );
00270 CL_ParsePacketEntities( msg, old, &newSnap );
00271
00272
00273
00274 if ( !newSnap.valid ) {
00275 return;
00276 }
00277
00278
00279
00280
00281
00282 oldMessageNum = cl.snap.messageNum + 1;
00283
00284 if ( newSnap.messageNum - oldMessageNum >= PACKET_BACKUP ) {
00285 oldMessageNum = newSnap.messageNum - ( PACKET_BACKUP - 1 );
00286 }
00287 for ( ; oldMessageNum < newSnap.messageNum ; oldMessageNum++ ) {
00288 cl.snapshots[oldMessageNum & PACKET_MASK].valid = qfalse;
00289 }
00290
00291
00292 cl.snap = newSnap;
00293 cl.snap.ping = 999;
00294
00295 for ( i = 0 ; i < PACKET_BACKUP ; i++ ) {
00296 packetNum = ( clc.netchan.outgoingSequence - 1 - i ) & PACKET_MASK;
00297 if ( cl.snap.ps.commandTime >= cl.outPackets[ packetNum ].p_serverTime ) {
00298 cl.snap.ping = cls.realtime - cl.outPackets[ packetNum ].p_realtime;
00299 break;
00300 }
00301 }
00302
00303 cl.snapshots[cl.snap.messageNum & PACKET_MASK] = cl.snap;
00304
00305 if (cl_shownet->integer == 3) {
00306 Com_Printf( " snapshot:%i delta:%i ping:%i\n", cl.snap.messageNum,
00307 cl.snap.deltaNum, cl.snap.ping );
00308 }
00309
00310 cl.newSnapshots = qtrue;
00311 }
00312
00313
00314
00315
00316 int cl_connectedToPureServer;
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327 void CL_SystemInfoChanged( void ) {
00328 char *systemInfo;
00329 const char *s, *t;
00330 char key[BIG_INFO_KEY];
00331 char value[BIG_INFO_VALUE];
00332 qboolean gameSet;
00333
00334 systemInfo = cl.gameState.stringData + cl.gameState.stringOffsets[ CS_SYSTEMINFO ];
00335
00336
00337
00338
00339 cl.serverId = atoi( Info_ValueForKey( systemInfo, "sv_serverid" ) );
00340
00341
00342 if ( clc.demoplaying ) {
00343 return;
00344 }
00345
00346 s = Info_ValueForKey( systemInfo, "sv_cheats" );
00347 if ( atoi(s) == 0 ) {
00348 Cvar_SetCheatState();
00349 }
00350
00351
00352 s = Info_ValueForKey( systemInfo, "sv_paks" );
00353 t = Info_ValueForKey( systemInfo, "sv_pakNames" );
00354 FS_PureServerSetLoadedPaks( s, t );
00355
00356 s = Info_ValueForKey( systemInfo, "sv_referencedPaks" );
00357 t = Info_ValueForKey( systemInfo, "sv_referencedPakNames" );
00358 FS_PureServerSetReferencedPaks( s, t );
00359
00360 gameSet = qfalse;
00361
00362 s = systemInfo;
00363 while ( s ) {
00364 Info_NextPair( &s, key, value );
00365 if ( !key[0] ) {
00366 break;
00367 }
00368
00369 if ( !Q_stricmp( key, "fs_game" ) ) {
00370 gameSet = qtrue;
00371 }
00372
00373 Cvar_Set( key, value );
00374 }
00375
00376 if ( !gameSet && *Cvar_VariableString("fs_game") ) {
00377 Cvar_Set( "fs_game", "" );
00378 }
00379 cl_connectedToPureServer = Cvar_VariableValue( "sv_pure" );
00380 }
00381
00382
00383
00384
00385
00386
00387 void CL_ParseGamestate( msg_t *msg ) {
00388 int i;
00389 entityState_t *es;
00390 int newnum;
00391 entityState_t nullstate;
00392 int cmd;
00393 char *s;
00394
00395 Con_Close();
00396
00397 clc.connectPacketCount = 0;
00398
00399
00400 CL_ClearState();
00401
00402
00403 clc.serverCommandSequence = MSG_ReadLong( msg );
00404
00405
00406 cl.gameState.dataCount = 1;
00407 while ( 1 ) {
00408 cmd = MSG_ReadByte( msg );
00409
00410 if ( cmd == svc_EOF ) {
00411 break;
00412 }
00413
00414 if ( cmd == svc_configstring ) {
00415 int len;
00416
00417 i = MSG_ReadShort( msg );
00418 if ( i < 0 || i >= MAX_CONFIGSTRINGS ) {
00419 Com_Error( ERR_DROP, "configstring > MAX_CONFIGSTRINGS" );
00420 }
00421 s = MSG_ReadBigString( msg );
00422 len = strlen( s );
00423
00424 if ( len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS ) {
00425 Com_Error( ERR_DROP, "MAX_GAMESTATE_CHARS exceeded" );
00426 }
00427
00428
00429 cl.gameState.stringOffsets[ i ] = cl.gameState.dataCount;
00430 Com_Memcpy( cl.gameState.stringData + cl.gameState.dataCount, s, len + 1 );
00431 cl.gameState.dataCount += len + 1;
00432 } else if ( cmd == svc_baseline ) {
00433 newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
00434 if ( newnum < 0 || newnum >= MAX_GENTITIES ) {
00435 Com_Error( ERR_DROP, "Baseline number out of range: %i", newnum );
00436 }
00437 Com_Memset (&nullstate, 0, sizeof(nullstate));
00438 es = &cl.entityBaselines[ newnum ];
00439 MSG_ReadDeltaEntity( msg, &nullstate, es, newnum );
00440 } else {
00441 Com_Error( ERR_DROP, "CL_ParseGamestate: bad command byte" );
00442 }
00443 }
00444
00445 clc.clientNum = MSG_ReadLong(msg);
00446
00447 clc.checksumFeed = MSG_ReadLong( msg );
00448
00449
00450 CL_SystemInfoChanged();
00451
00452
00453 FS_ConditionalRestart( clc.checksumFeed );
00454
00455
00456
00457 CL_InitDownloads();
00458
00459
00460 Cvar_Set( "cl_paused", "0" );
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473 void CL_ParseDownload ( msg_t *msg ) {
00474 int size;
00475 unsigned char data[MAX_MSGLEN];
00476 int block;
00477
00478
00479 block = MSG_ReadShort ( msg );
00480
00481 if ( !block )
00482 {
00483
00484 clc.downloadSize = MSG_ReadLong ( msg );
00485
00486 Cvar_SetValue( "cl_downloadSize", clc.downloadSize );
00487
00488 if (clc.downloadSize < 0)
00489 {
00490 Com_Error(ERR_DROP, MSG_ReadString( msg ) );
00491 return;
00492 }
00493 }
00494
00495 size = MSG_ReadShort ( msg );
00496 if (size > 0)
00497 MSG_ReadData( msg, data, size );
00498
00499 if (clc.downloadBlock != block) {
00500 Com_DPrintf( "CL_ParseDownload: Expected block %d, got %d\n", clc.downloadBlock, block);
00501 return;
00502 }
00503
00504
00505 if (!clc.download)
00506 {
00507 if (!*clc.downloadTempName) {
00508 Com_Printf("Server sending download, but no download was requested\n");
00509 CL_AddReliableCommand( "stopdl" );
00510 return;
00511 }
00512
00513 clc.download = FS_SV_FOpenFileWrite( clc.downloadTempName );
00514
00515 if (!clc.download) {
00516 Com_Printf( "Could not create %s\n", clc.downloadTempName );
00517 CL_AddReliableCommand( "stopdl" );
00518 CL_NextDownload();
00519 return;
00520 }
00521 }
00522
00523 if (size)
00524 FS_Write( data, size, clc.download );
00525
00526 CL_AddReliableCommand( va("nextdl %d", clc.downloadBlock) );
00527 clc.downloadBlock++;
00528
00529 clc.downloadCount += size;
00530
00531
00532 Cvar_SetValue( "cl_downloadCount", clc.downloadCount );
00533
00534 if (!size) {
00535 if (clc.download) {
00536 FS_FCloseFile( clc.download );
00537 clc.download = 0;
00538
00539
00540 FS_SV_Rename ( clc.downloadTempName, clc.downloadName );
00541 }
00542 *clc.downloadTempName = *clc.downloadName = 0;
00543 Cvar_Set( "cl_downloadName", "" );
00544
00545
00546
00547
00548
00549
00550 CL_WritePacket();
00551 CL_WritePacket();
00552
00553
00554 CL_NextDownload ();
00555 }
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 void CL_ParseCommandString( msg_t *msg ) {
00567 char *s;
00568 int seq;
00569 int index;
00570
00571 seq = MSG_ReadLong( msg );
00572 s = MSG_ReadString( msg );
00573
00574
00575 if ( clc.serverCommandSequence >= seq ) {
00576 return;
00577 }
00578 clc.serverCommandSequence = seq;
00579
00580 index = seq & (MAX_RELIABLE_COMMANDS-1);
00581 Q_strncpyz( clc.serverCommands[ index ], s, sizeof( clc.serverCommands[ index ] ) );
00582 }
00583
00584
00585
00586
00587
00588
00589
00590 void CL_ParseServerMessage( msg_t *msg ) {
00591 int cmd;
00592
00593 if ( cl_shownet->integer == 1 ) {
00594 Com_Printf ("%i ",msg->cursize);
00595 } else if ( cl_shownet->integer >= 2 ) {
00596 Com_Printf ("------------------\n");
00597 }
00598
00599 MSG_Bitstream(msg);
00600
00601
00602 clc.reliableAcknowledge = MSG_ReadLong( msg );
00603
00604 if ( clc.reliableAcknowledge < clc.reliableSequence - MAX_RELIABLE_COMMANDS ) {
00605 clc.reliableAcknowledge = clc.reliableSequence;
00606 }
00607
00608
00609
00610
00611 while ( 1 ) {
00612 if ( msg->readcount > msg->cursize ) {
00613 Com_Error (ERR_DROP,"CL_ParseServerMessage: read past end of server message");
00614 break;
00615 }
00616
00617 cmd = MSG_ReadByte( msg );
00618
00619 if ( cmd == svc_EOF) {
00620 SHOWNET( msg, "END OF MESSAGE" );
00621 break;
00622 }
00623
00624 if ( cl_shownet->integer >= 2 ) {
00625 if ( !svc_strings[cmd] ) {
00626 Com_Printf( "%3i:BAD CMD %i\n", msg->readcount-1, cmd );
00627 } else {
00628 SHOWNET( msg, svc_strings[cmd] );
00629 }
00630 }
00631
00632
00633 switch ( cmd ) {
00634 default:
00635 Com_Error (ERR_DROP,"CL_ParseServerMessage: Illegible server message\n");
00636 break;
00637 case svc_nop:
00638 break;
00639 case svc_serverCommand:
00640 CL_ParseCommandString( msg );
00641 break;
00642 case svc_gamestate:
00643 CL_ParseGamestate( msg );
00644 break;
00645 case svc_snapshot:
00646 CL_ParseSnapshot( msg );
00647 break;
00648 case svc_download:
00649 CL_ParseDownload( msg );
00650 break;
00651 }
00652 }
00653 }
00654
00655