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 // cl_parse.c -- parse a message received from the server 21 22 #include "quakedef.h" 23 24 const char *svc_strings[] = 25 { 26 "svc_bad", 27 "svc_nop", 28 "svc_disconnect", 29 "svc_updatestat", 30 "svc_version", // [long] server version 31 "svc_setview", // [short] entity number 32 "svc_sound", // <see code> 33 "svc_time", // [float] server time 34 "svc_print", // [string] null terminated string 35 "svc_stufftext", // [string] stuffed into client's console buffer 36 // the string should be \n terminated 37 "svc_setangle", // [vec3] set the view angle to this absolute value 38 39 "svc_serverinfo", // [long] version 40 // [string] signon string 41 // [string]..[0]model cache [string]...[0]sounds cache 42 // [string]..[0]item cache 43 "svc_lightstyle", // [byte] [string] 44 "svc_updatename", // [byte] [string] 45 "svc_updatefrags", // [byte] [short] 46 "svc_clientdata", // <shortbits + data> 47 "svc_stopsound", // <see code> 48 "svc_updatecolors", // [byte] [byte] 49 "svc_particle", // [vec3] <variable> 50 "svc_damage", // [byte] impact [byte] blood [vec3] from 51 52 "svc_spawnstatic", 53 "OBSOLETE svc_spawnbinary", 54 "svc_spawnbaseline", 55 56 "svc_temp_entity", // <variable> 57 "svc_setpause", 58 "svc_signonnum", 59 "svc_centerprint", 60 "svc_killedmonster", 61 "svc_foundsecret", 62 "svc_spawnstaticsound", 63 "svc_intermission", 64 "svc_finale", // [string] music [string] text 65 "svc_cdtrack", // [byte] track [byte] looptrack 66 "svc_sellscreen", 67 "svc_cutscene" 68 }; 69 70 //============================================================================= 71 72 /* 73 =============== 74 CL_EntityNum 75 76 This error checks and tracks the total number of entities 77 =============== 78 */ 79 entity_t *CL_EntityNum (int num) 80 { 81 if (num >= cl.num_entities) 82 { 83 if (num >= MAX_EDICTS) 84 Host_Error ("CL_EntityNum: %i is an invalid number",num); 85 while (cl.num_entities<=num) 86 { 87 cl_entities[cl.num_entities].colormap = vid.colormap; 88 cl.num_entities++; 89 } 90 } 91 92 return &cl_entities[num]; 93 } 94 95 96 /* 97 ================== 98 CL_ParseStartSoundPacket 99 ================== 100 */ 101 void CL_ParseStartSoundPacket(void) 102 { 103 vec3_t pos; 104 int channel, ent; 105 int sound_num; 106 int volume; 107 int field_mask; 108 float attenuation; 109 int i; 110 111 field_mask = MSG_ReadByte(); 112 113 if (field_mask & SND_VOLUME) 114 volume = MSG_ReadByte (); 115 else 116 volume = DEFAULT_SOUND_PACKET_VOLUME; 117 118 if (field_mask & SND_ATTENUATION) 119 attenuation = MSG_ReadByte () / 64.0; 120 else 121 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION; 122 123 channel = MSG_ReadShort (); 124 sound_num = MSG_ReadByte (); 125 126 ent = channel >> 3; 127 channel &= 7; 128 129 if (ent > MAX_EDICTS) 130 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent); 131 132 for (i=0 ; i<3 ; i++) 133 pos[i] = MSG_ReadCoord (); 134 135 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation); 136 } 137 138 /* 139 ================== 140 CL_KeepaliveMessage 141 142 When the client is taking a long time to load stuff, send keepalive messages 143 so the server doesn't disconnect. 144 ================== 145 */ 146 void CL_KeepaliveMessage (void) 147 { 148 float time; 149 static float lastmsg; 150 int ret; 151 sizebuf_t old; 152 byte olddata[8192]; 153 154 if (sv.active) 155 return; // no need if server is local 156 if (cls.demoplayback) 157 return; 158 159 // read messages from server, should just be nops 160 old = net_message; 161 memcpy (olddata, net_message.data, net_message.cursize); 162 163 do 164 { 165 ret = CL_GetMessage (); 166 switch (ret) 167 { 168 default: 169 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed"); 170 case 0: 171 break; // nothing waiting 172 case 1: 173 Host_Error ("CL_KeepaliveMessage: received a message"); 174 break; 175 case 2: 176 if (MSG_ReadByte() != svc_nop) 177 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop"); 178 break; 179 } 180 } while (ret); 181 182 net_message = old; 183 memcpy (net_message.data, olddata, net_message.cursize); 184 185 // check time 186 time = Sys_FloatTime (); 187 if (time - lastmsg < 5) 188 return; 189 lastmsg = time; 190 191 // write out a nop 192 Con_Printf ("--> client to server keepalive\n"); 193 194 MSG_WriteByte (&cls.message, clc_nop); 195 NET_SendMessage (cls.netcon, &cls.message); 196 SZ_Clear (&cls.message); 197 } 198 199 /* 200 ================== 201 CL_ParseServerInfo 202 ================== 203 */ 204 void CL_ParseServerInfo (void) 205 { 206 char *str; 207 int i; 208 int nummodels, numsounds; 209 char model_precache[MAX_MODELS][MAX_QPATH]; 210 char sound_precache[MAX_SOUNDS][MAX_QPATH]; 211 212 Con_DPrintf ("Serverinfo packet received.\n"); 213 // 214 // wipe the client_state_t struct 215 // 216 CL_ClearState (); 217 218 // parse protocol version number 219 i = MSG_ReadLong (); 220 if (i != PROTOCOL_VERSION) 221 { 222 Con_Printf ("Server returned version %i, not %i", i, PROTOCOL_VERSION); 223 return; 224 } 225 226 // parse maxclients 227 cl.maxclients = MSG_ReadByte (); 228 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD) 229 { 230 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients); 231 return; 232 } 233 cl.scores = (scoreboard_t*) Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores"); 234 235 // parse gametype 236 cl.gametype = MSG_ReadByte (); 237 238 // parse signon message 239 str = MSG_ReadString (); 240 strncpy (cl.levelname, str, sizeof(cl.levelname)-1); 241 242 // seperate the printfs so the server message can have a color 243 Con_Printf("\n\n\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37\n\n"); 244 Con_Printf ("%c%s\n", 2, str); 245 246 // 247 // first we go through and touch all of the precache data that still 248 // happens to be in the cache, so precaching something else doesn't 249 // needlessly purge it 250 // 251 252 // precache models 253 memset (cl.model_precache, 0, sizeof(cl.model_precache)); 254 for (nummodels=1 ; ; nummodels++) 255 { 256 str = MSG_ReadString (); 257 if (!str[0]) 258 break; 259 if (nummodels==MAX_MODELS) 260 { 261 Con_Printf ("Server sent too many model precaches\n"); 262 return; 263 } 264 strcpy (model_precache[nummodels], str); 265 Mod_TouchModel (str); 266 } 267 268 // precache sounds 269 memset (cl.sound_precache, 0, sizeof(cl.sound_precache)); 270 for (numsounds=1 ; ; numsounds++) 271 { 272 str = MSG_ReadString (); 273 if (!str[0]) 274 break; 275 if (numsounds==MAX_SOUNDS) 276 { 277 Con_Printf ("Server sent too many sound precaches\n"); 278 return; 279 } 280 strcpy (sound_precache[numsounds], str); 281 S_TouchSound (str); 282 } 283 284 // 285 // now we try to load everything else until a cache allocation fails 286 // 287 288 for (i=1 ; i<nummodels ; i++) 289 { 290 cl.model_precache[i] = Mod_ForName (model_precache[i], false); 291 if (cl.model_precache[i] == NULL) 292 { 293 Con_Printf("Model %s not found\n", model_precache[i]); 294 return; 295 } 296 CL_KeepaliveMessage (); 297 } 298 299 S_BeginPrecaching (); 300 for (i=1 ; i<numsounds ; i++) 301 { 302 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]); 303 CL_KeepaliveMessage (); 304 } 305 S_EndPrecaching (); 306 307 308 // local state 309 cl_entities[0].model = cl.worldmodel = cl.model_precache[1]; 310 311 R_NewMap (); 312 313 Hunk_Check (); // make sure nothing is hurt 314 315 noclip_anglehack = false; // noclip is turned off at start 316 } 317 318 319 /* 320 ================== 321 CL_ParseUpdate 322 323 Parse an entity update message from the server 324 If an entities model or origin changes from frame to frame, it must be 325 relinked. Other attributes can change without relinking. 326 ================== 327 */ 328 int bitcounts[16]; 329 330 void CL_ParseUpdate (int bits) 331 { 332 int i; 333 model_t *model; 334 int modnum; 335 qboolean forcelink; 336 entity_t *ent; 337 int num; 338 int skin; 339 340 if (cls.signon == SIGNONS - 1) 341 { // first update is the final signon stage 342 cls.signon = SIGNONS; 343 CL_SignonReply (); 344 } 345 346 if (bits & U_MOREBITS) 347 { 348 i = MSG_ReadByte (); 349 bits |= (i<<8); 350 } 351 352 if (bits & U_LONGENTITY) 353 num = MSG_ReadShort (); 354 else 355 num = MSG_ReadByte (); 356 357 ent = CL_EntityNum (num); 358 359 for (i=0 ; i<16 ; i++) 360 if (bits&(1<<i)) 361 bitcounts[i]++; 362 363 if (ent->msgtime != cl.mtime[1]) 364 forcelink = true; // no previous frame to lerp from 365 else 366 forcelink = false; 367 368 ent->msgtime = cl.mtime[0]; 369 370 if (bits & U_MODEL) 371 { 372 modnum = MSG_ReadByte (); 373 if (modnum >= MAX_MODELS) 374 Host_Error ("CL_ParseModel: bad modnum"); 375 } 376 else 377 modnum = ent->baseline.modelindex; 378 379 model = cl.model_precache[modnum]; 380 if (model != ent->model) 381 { 382 ent->model = model; 383 // automatic animation (torches, etc) can be either all together 384 // or randomized 385 if (model) 386 { 387 if (model->synctype == ST_RAND) 388 ent->syncbase = (float)(rand()&0x7fff) / 0x7fff; 389 else 390 ent->syncbase = 0.0; 391 } 392 else 393 forcelink = true; // hack to make null model players work 394 #ifdef GLQUAKE 395 if (num > 0 && num <= cl.maxclients) 396 R_TranslatePlayerSkin (num - 1); 397 #endif 398 } 399 400 if (bits & U_FRAME) 401 ent->frame = MSG_ReadByte (); 402 else 403 ent->frame = ent->baseline.frame; 404 405 if (bits & U_COLORMAP) 406 i = MSG_ReadByte(); 407 else 408 i = ent->baseline.colormap; 409 if (!i) 410 ent->colormap = vid.colormap; 411 else 412 { 413 if (i > cl.maxclients) 414 Sys_Error ("i >= cl.maxclients"); 415 ent->colormap = cl.scores[i-1].translations; 416 } 417 418 #ifdef GLQUAKE 419 if (bits & U_SKIN) 420 skin = MSG_ReadByte(); 421 else 422 skin = ent->baseline.skin; 423 if (skin != ent->skinnum) { 424 ent->skinnum = skin; 425 if (num > 0 && num <= cl.maxclients) 426 R_TranslatePlayerSkin (num - 1); 427 } 428 429 #else 430 431 if (bits & U_SKIN) 432 ent->skinnum = MSG_ReadByte(); 433 else 434 ent->skinnum = ent->baseline.skin; 435 #endif 436 437 if (bits & U_EFFECTS) 438 ent->effects = MSG_ReadByte(); 439 else 440 ent->effects = ent->baseline.effects; 441 442 // shift the known values for interpolation 443 VectorCopy (ent->msg_origins[0], ent->msg_origins[1]); 444 VectorCopy (ent->msg_angles[0], ent->msg_angles[1]); 445 446 if (bits & U_ORIGIN1) 447 ent->msg_origins[0][0] = MSG_ReadCoord (); 448 else 449 ent->msg_origins[0][0] = ent->baseline.origin[0]; 450 if (bits & U_ANGLE1) 451 ent->msg_angles[0][0] = MSG_ReadAngle(); 452 else 453 ent->msg_angles[0][0] = ent->baseline.angles[0]; 454 455 if (bits & U_ORIGIN2) 456 ent->msg_origins[0][1] = MSG_ReadCoord (); 457 else 458 ent->msg_origins[0][1] = ent->baseline.origin[1]; 459 if (bits & U_ANGLE2) 460 ent->msg_angles[0][1] = MSG_ReadAngle(); 461 else 462 ent->msg_angles[0][1] = ent->baseline.angles[1]; 463 464 if (bits & U_ORIGIN3) 465 ent->msg_origins[0][2] = MSG_ReadCoord (); 466 else 467 ent->msg_origins[0][2] = ent->baseline.origin[2]; 468 if (bits & U_ANGLE3) 469 ent->msg_angles[0][2] = MSG_ReadAngle(); 470 else 471 ent->msg_angles[0][2] = ent->baseline.angles[2]; 472 473 if ( bits & U_NOLERP ) 474 ent->forcelink = true; 475 476 if ( forcelink ) 477 { // didn't have an update last message 478 VectorCopy (ent->msg_origins[0], ent->msg_origins[1]); 479 VectorCopy (ent->msg_origins[0], ent->origin); 480 VectorCopy (ent->msg_angles[0], ent->msg_angles[1]); 481 VectorCopy (ent->msg_angles[0], ent->angles); 482 ent->forcelink = true; 483 } 484 } 485 486 /* 487 ================== 488 CL_ParseBaseline 489 ================== 490 */ 491 void CL_ParseBaseline (entity_t *ent) 492 { 493 int i; 494 495 ent->baseline.modelindex = MSG_ReadByte (); 496 ent->baseline.frame = MSG_ReadByte (); 497 ent->baseline.colormap = MSG_ReadByte(); 498 ent->baseline.skin = MSG_ReadByte(); 499 for (i=0 ; i<3 ; i++) 500 { 501 ent->baseline.origin[i] = MSG_ReadCoord (); 502 ent->baseline.angles[i] = MSG_ReadAngle (); 503 } 504 } 505 506 507 /* 508 ================== 509 CL_ParseClientdata 510 511 Server information pertaining to this client only 512 ================== 513 */ 514 void CL_ParseClientdata (int bits) 515 { 516 int i, j; 517 518 if (bits & SU_VIEWHEIGHT) 519 cl.viewheight = MSG_ReadChar (); 520 else 521 cl.viewheight = DEFAULT_VIEWHEIGHT; 522 523 if (bits & SU_IDEALPITCH) 524 cl.idealpitch = MSG_ReadChar (); 525 else 526 cl.idealpitch = 0; 527 528 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]); 529 for (i=0 ; i<3 ; i++) 530 { 531 if (bits & (SU_PUNCH1<<i) ) 532 cl.punchangle[i] = MSG_ReadChar(); 533 else 534 cl.punchangle[i] = 0; 535 if (bits & (SU_VELOCITY1<<i) ) 536 cl.mvelocity[0][i] = MSG_ReadChar()*16; 537 else 538 cl.mvelocity[0][i] = 0; 539 } 540 541 // [always sent] if (bits & SU_ITEMS) 542 i = MSG_ReadLong (); 543 544 if (cl.items != i) 545 { // set flash times 546 Sbar_Changed (); 547 for (j=0 ; j<32 ; j++) 548 if ( (i & (1<<j)) && !(cl.items & (1<<j))) 549 cl.item_gettime[j] = cl.time; 550 cl.items = i; 551 } 552 553 cl.onground = (bits & SU_ONGROUND) != 0; 554 cl.inwater = (bits & SU_INWATER) != 0; 555 556 if (bits & SU_WEAPONFRAME) 557 cl.stats[STAT_WEAPONFRAME] = MSG_ReadByte (); 558 else 559 cl.stats[STAT_WEAPONFRAME] = 0; 560 561 if (bits & SU_ARMOR) 562 i = MSG_ReadByte (); 563 else 564 i = 0; 565 if (cl.stats[STAT_ARMOR] != i) 566 { 567 cl.stats[STAT_ARMOR] = i; 568 Sbar_Changed (); 569 } 570 571 if (bits & SU_WEAPON) 572 i = MSG_ReadByte (); 573 else 574 i = 0; 575 if (cl.stats[STAT_WEAPON] != i) 576 { 577 cl.stats[STAT_WEAPON] = i; 578 Sbar_Changed (); 579 } 580 581 i = MSG_ReadShort (); 582 if (cl.stats[STAT_HEALTH] != i) 583 { 584 cl.stats[STAT_HEALTH] = i; 585 Sbar_Changed (); 586 } 587 588 i = MSG_ReadByte (); 589 if (cl.stats[STAT_AMMO] != i) 590 { 591 cl.stats[STAT_AMMO] = i; 592 Sbar_Changed (); 593 } 594 595 for (i=0 ; i<4 ; i++) 596 { 597 j = MSG_ReadByte (); 598 if (cl.stats[STAT_SHELLS+i] != j) 599 { 600 cl.stats[STAT_SHELLS+i] = j; 601 Sbar_Changed (); 602 } 603 } 604 605 i = MSG_ReadByte (); 606 607 if (standard_quake) 608 { 609 if (cl.stats[STAT_ACTIVEWEAPON] != i) 610 { 611 cl.stats[STAT_ACTIVEWEAPON] = i; 612 Sbar_Changed (); 613 } 614 } 615 else 616 { 617 if (cl.stats[STAT_ACTIVEWEAPON] != (1<<i)) 618 { 619 cl.stats[STAT_ACTIVEWEAPON] = (1<<i); 620 Sbar_Changed (); 621 } 622 } 623 } 624 625 /* 626 ===================== 627 CL_NewTranslation 628 ===================== 629 */ 630 void CL_NewTranslation (int slot) 631 { 632 int i, j; 633 int top, bottom; 634 byte *dest, *source; 635 636 if (slot > cl.maxclients) 637 Sys_Error ("CL_NewTranslation: slot > cl.maxclients"); 638 dest = cl.scores[slot].translations; 639 source = vid.colormap; 640 memcpy (dest, vid.colormap, sizeof(cl.scores[slot].translations)); 641 top = cl.scores[slot].colors & 0xf0; 642 bottom = (cl.scores[slot].colors &15)<<4; 643 #ifdef GLQUAKE 644 R_TranslatePlayerSkin (slot); 645 #endif 646 647 for (i=0 ; i<VID_GRADES ; i++, dest += 256, source+=256) 648 { 649 if (top < 128) // the artists made some backwards ranges. sigh. 650 memcpy (dest + TOP_RANGE, source + top, 16); 651 else 652 for (j=0 ; j<16 ; j++) 653 dest[TOP_RANGE+j] = source[top+15-j]; 654 655 if (bottom < 128) 656 memcpy (dest + BOTTOM_RANGE, source + bottom, 16); 657 else 658 for (j=0 ; j<16 ; j++) 659 dest[BOTTOM_RANGE+j] = source[bottom+15-j]; 660 } 661 } 662 663 /* 664 ===================== 665 CL_ParseStatic 666 ===================== 667 */ 668 void CL_ParseStatic (void) 669 { 670 entity_t *ent; 671 int i; 672 673 i = cl.num_statics; 674 if (i >= MAX_STATIC_ENTITIES) 675 Host_Error ("Too many static entities"); 676 ent = &cl_static_entities[i]; 677 cl.num_statics++; 678 CL_ParseBaseline (ent); 679 680 // copy it to the current state 681 ent->model = cl.model_precache[ent->baseline.modelindex]; 682 ent->frame = ent->baseline.frame; 683 ent->colormap = vid.colormap; 684 ent->skinnum = ent->baseline.skin; 685 ent->effects = ent->baseline.effects; 686 687 VectorCopy (ent->baseline.origin, ent->origin); 688 VectorCopy (ent->baseline.angles, ent->angles); 689 R_AddEfrags (ent); 690 } 691 692 /* 693 =================== 694 CL_ParseStaticSound 695 =================== 696 */ 697 void CL_ParseStaticSound (void) 698 { 699 vec3_t org; 700 int sound_num, vol, atten; 701 int i; 702 703 for (i=0 ; i<3 ; i++) 704 org[i] = MSG_ReadCoord (); 705 sound_num = MSG_ReadByte (); 706 vol = MSG_ReadByte (); 707 atten = MSG_ReadByte (); 708 709 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten); 710 } 711 712 713 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x); 714 715 /* 716 ===================== 717 CL_ParseServerMessage 718 ===================== 719 */ 720 void CL_ParseServerMessage (void) 721 { 722 int cmd; 723 int i; 724 725 // 726 // if recording demos, copy the message out 727 // 728 if (cl_shownet.value == 1) 729 Con_Printf ("%i ",net_message.cursize); 730 else if (cl_shownet.value == 2) 731 Con_Printf ("------------------\n"); 732 733 cl.onground = false; // unless the server says otherwise 734 // 735 // parse the message 736 // 737 MSG_BeginReading (); 738 739 while (1) 740 { 741 if (msg_badread) 742 Host_Error ("CL_ParseServerMessage: Bad server message"); 743 744 cmd = MSG_ReadByte (); 745 746 if (cmd == -1) 747 { 748 SHOWNET("END OF MESSAGE"); 749 return; // end of message 750 } 751 752 // if the high bit of the command byte is set, it is a fast update 753 if (cmd & 128) 754 { 755 SHOWNET("fast update"); 756 CL_ParseUpdate (cmd&127); 757 continue; 758 } 759 760 SHOWNET(svc_strings[cmd]); 761 762 // other commands 763 switch (cmd) 764 { 765 default: 766 Host_Error ("CL_ParseServerMessage: Illegible server message\n"); 767 break; 768 769 case svc_nop: 770 // Con_Printf ("svc_nop\n"); 771 break; 772 773 case svc_time: 774 cl.mtime[1] = cl.mtime[0]; 775 cl.mtime[0] = MSG_ReadFloat (); 776 break; 777 778 case svc_clientdata: 779 i = MSG_ReadShort (); 780 CL_ParseClientdata (i); 781 break; 782 783 case svc_version: 784 i = MSG_ReadLong (); 785 if (i != PROTOCOL_VERSION) 786 Host_Error ("CL_ParseServerMessage: Server is protocol %i instead of %i\n", i, PROTOCOL_VERSION); 787 break; 788 789 case svc_disconnect: 790 Host_EndGame ("Server disconnected\n"); 791 792 case svc_print: 793 Con_Printf ("%s", MSG_ReadString ()); 794 break; 795 796 case svc_centerprint: 797 SCR_CenterPrint (MSG_ReadString ()); 798 break; 799 800 case svc_stufftext: 801 Cbuf_AddText (MSG_ReadString ()); 802 break; 803 804 case svc_damage: 805 V_ParseDamage (); 806 break; 807 808 case svc_serverinfo: 809 CL_ParseServerInfo (); 810 vid.recalc_refdef = true; // leave intermission full screen 811 break; 812 813 case svc_setangle: 814 for (i=0 ; i<3 ; i++) 815 cl.viewangles[i] = MSG_ReadAngle (); 816 break; 817 818 case svc_setview: 819 cl.viewentity = MSG_ReadShort (); 820 break; 821 822 case svc_lightstyle: 823 i = MSG_ReadByte (); 824 if (i >= MAX_LIGHTSTYLES) 825 Sys_Error ("svc_lightstyle > MAX_LIGHTSTYLES"); 826 Q_strcpy (cl_lightstyle[i].map, MSG_ReadString()); 827 cl_lightstyle[i].length = Q_strlen(cl_lightstyle[i].map); 828 break; 829 830 case svc_sound: 831 CL_ParseStartSoundPacket(); 832 break; 833 834 case svc_stopsound: 835 i = MSG_ReadShort(); 836 S_StopSound(i>>3, i&7); 837 break; 838 839 case svc_updatename: 840 Sbar_Changed (); 841 i = MSG_ReadByte (); 842 if (i >= cl.maxclients) 843 Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD"); 844 strcpy (cl.scores[i].name, MSG_ReadString ()); 845 break; 846 847 case svc_updatefrags: 848 Sbar_Changed (); 849 i = MSG_ReadByte (); 850 if (i >= cl.maxclients) 851 Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD"); 852 cl.scores[i].frags = MSG_ReadShort (); 853 break; 854 855 case svc_updatecolors: 856 Sbar_Changed (); 857 i = MSG_ReadByte (); 858 if (i >= cl.maxclients) 859 Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD"); 860 cl.scores[i].colors = MSG_ReadByte (); 861 CL_NewTranslation (i); 862 break; 863 864 case svc_particle: 865 R_ParseParticleEffect (); 866 break; 867 868 case svc_spawnbaseline: 869 i = MSG_ReadShort (); 870 // must use CL_EntityNum() to force cl.num_entities up 871 CL_ParseBaseline (CL_EntityNum(i)); 872 break; 873 case svc_spawnstatic: 874 CL_ParseStatic (); 875 break; 876 case svc_temp_entity: 877 CL_ParseTEnt (); 878 break; 879 880 case svc_setpause: 881 { 882 cl.paused = MSG_ReadByte (); 883 884 if (cl.paused) 885 { 886 CDAudio_Pause (); 887 #ifdef _WIN32 888 VID_HandlePause (true); 889 #endif 890 } 891 else 892 { 893 CDAudio_Resume (); 894 #ifdef _WIN32 895 VID_HandlePause (false); 896 #endif 897 } 898 } 899 break; 900 901 case svc_signonnum: 902 i = MSG_ReadByte (); 903 if (i <= cls.signon) 904 Host_Error ("Received signon %i when at %i", i, cls.signon); 905 cls.signon = i; 906 CL_SignonReply (); 907 break; 908 909 case svc_killedmonster: 910 cl.stats[STAT_MONSTERS]++; 911 break; 912 913 case svc_foundsecret: 914 cl.stats[STAT_SECRETS]++; 915 break; 916 917 case svc_updatestat: 918 i = MSG_ReadByte (); 919 if (i < 0 || i >= MAX_CL_STATS) 920 Sys_Error ("svc_updatestat: %i is invalid", i); 921 cl.stats[i] = MSG_ReadLong ();; 922 break; 923 924 case svc_spawnstaticsound: 925 CL_ParseStaticSound (); 926 break; 927 928 case svc_cdtrack: 929 cl.cdtrack = MSG_ReadByte (); 930 cl.looptrack = MSG_ReadByte (); 931 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) ) 932 CDAudio_Play ((byte)cls.forcetrack, true); 933 else 934 CDAudio_Play ((byte)cl.cdtrack, true); 935 break; 936 937 case svc_intermission: 938 cl.intermission = 1; 939 cl.completed_time = (int) cl.time; 940 vid.recalc_refdef = true; // go to full screen 941 break; 942 943 case svc_finale: 944 cl.intermission = 2; 945 cl.completed_time = (int) cl.time; 946 vid.recalc_refdef = true; // go to full screen 947 SCR_CenterPrint (MSG_ReadString ()); 948 break; 949 950 case svc_cutscene: 951 cl.intermission = 3; 952 cl.completed_time = (int) cl.time; 953 vid.recalc_refdef = true; // go to full screen 954 SCR_CenterPrint (MSG_ReadString ()); 955 break; 956 957 case svc_sellscreen: 958 Cmd_ExecuteString2 ("help", src_command); 959 break; 960 } 961 } 962 } 963 964