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