2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
20 // cl_parse.c -- parse a message received from the server
24 char *svc_strings[128] =
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
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
53 "OBSOLETE svc_spawnbinary",
56 "svc_temp_entity", // <variable>
62 "svc_spawnstaticsound",
64 "svc_finale", // [string] music [string] text
65 "svc_cdtrack", // [byte] track [byte] looptrack
68 "svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y
69 "svc_hidelmp", // [string] iconlabel
85 "svc_effect", // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
86 "svc_effect2", // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate
89 //=============================================================================
91 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
92 qboolean dpprotocol; // LordHavoc: whether or not the current network stream is the enhanced DarkPlaces protocol
98 This error checks and tracks the total number of entities
101 entity_t *CL_EntityNum (int num)
103 if (num >= cl.num_entities)
105 if (num >= MAX_EDICTS)
106 Host_Error ("CL_EntityNum: %i is an invalid number",num);
107 while (cl.num_entities<=num)
109 cl_entities[cl.num_entities].colormap = -1; // no special coloring
114 return &cl_entities[num];
120 CL_ParseStartSoundPacket
123 void CL_ParseStartSoundPacket(int largesoundindex)
133 field_mask = MSG_ReadByte();
135 if (field_mask & SND_VOLUME)
136 volume = MSG_ReadByte ();
138 volume = DEFAULT_SOUND_PACKET_VOLUME;
140 if (field_mask & SND_ATTENUATION)
141 attenuation = MSG_ReadByte () / 64.0;
143 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
145 channel = MSG_ReadShort ();
147 sound_num = (unsigned short) MSG_ReadShort ();
149 sound_num = MSG_ReadByte ();
151 if (sound_num >= MAX_SOUNDS)
152 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
157 if (ent > MAX_EDICTS)
158 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
160 for (i=0 ; i<3 ; i++)
161 pos[i] = MSG_ReadCoord ();
163 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
170 When the client is taking a long time to load stuff, send keepalive messages
171 so the server doesn't disconnect.
174 void CL_KeepaliveMessage (void)
177 static float lastmsg;
183 return; // no need if server is local
184 if (cls.demoplayback)
187 // read messages from server, should just be nops
189 memcpy (olddata, net_message.data, net_message.cursize);
193 ret = CL_GetMessage ();
197 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
199 break; // nothing waiting
201 Host_Error ("CL_KeepaliveMessage: received a message");
204 if (MSG_ReadByte() != svc_nop)
205 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
211 memcpy (net_message.data, olddata, net_message.cursize);
214 time = Sys_FloatTime ();
215 if (time - lastmsg < 5)
220 Con_Printf ("--> client to server keepalive\n");
222 MSG_WriteByte (&cls.message, clc_nop);
223 NET_SendMessage (cls.netcon, &cls.message);
224 SZ_Clear (&cls.message);
227 extern qboolean isworldmodel;
228 extern char skyname[];
229 extern void R_SetSkyBox (char *sky);
230 extern void FOG_clear();
231 extern cvar_t r_farclip;
233 void CL_ParseEntityLump(char *entdata)
236 char key[128], value[4096];
239 FOG_clear(); // LordHavoc: no fog until set
240 skyname[0] = 0; // LordHavoc: no enviroment mapped sky until set
241 r_farclip.value = 6144; // LordHavoc: default farclip distance
245 data = COM_Parse(data);
247 return; // valid exit
248 if (com_token[0] != '{')
252 data = COM_Parse(data);
255 if (com_token[0] == '}')
256 return; // since we're just parsing the first ent (worldspawn), exit
257 strcpy(key, com_token);
258 while (key[strlen(key)-1] == ' ') // remove trailing spaces
259 key[strlen(key)-1] = 0;
260 data = COM_Parse(data);
263 strcpy(value, com_token);
264 if (!strcmp("sky", key))
266 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
268 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
270 else if (!strcmp("farclip", key))
272 r_farclip.value = atof(value);
273 if (r_farclip.value < 64)
274 r_farclip.value = 64;
276 else if (!strcmp("fog", key))
278 scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
281 else if (!strcmp("fog_density", key))
282 fog_density = atof(value);
283 else if (!strcmp("fog_red", key))
284 fog_red = atof(value);
285 else if (!strcmp("fog_green", key))
286 fog_green = atof(value);
287 else if (!strcmp("fog_blue", key))
288 fog_blue = atof(value);
289 else if (!strcmp("wad", key)) // for HalfLife maps
292 for (i = 0;i < 4096;i++)
293 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
299 // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
300 if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
302 else if (value[i] == ';' || value[i] == 0)
306 strcpy(wadname, "textures/");
307 strcat(wadname, &value[j]);
308 W_LoadTextureWadFile (wadname, false);
324 extern cvar_t demo_nehahra;
325 void CL_ParseServerInfo (void)
329 int nummodels, numsounds;
330 char model_precache[MAX_MODELS][MAX_QPATH];
331 char sound_precache[MAX_SOUNDS][MAX_QPATH];
333 Con_DPrintf ("Serverinfo packet received.\n");
335 // wipe the client_state_t struct
339 // parse protocol version number
341 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
343 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
346 Nehahrademcompatibility = false;
348 Nehahrademcompatibility = true;
349 if (cls.demoplayback && demo_nehahra.value)
350 Nehahrademcompatibility = true;
351 dpprotocol = i == DPPROTOCOL_VERSION;
354 cl.maxclients = MSG_ReadByte ();
355 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
357 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
360 cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
363 cl.gametype = MSG_ReadByte ();
365 // parse signon message
366 str = MSG_ReadString ();
367 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
369 // seperate the printfs so the server message can have a color
370 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
372 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");
373 Con_Printf ("%c%s\n", 2, str);
377 // first we go through and touch all of the precache data that still
378 // happens to be in the cache, so precaching something else doesn't
379 // needlessly purge it
383 memset (cl.model_precache, 0, sizeof(cl.model_precache));
384 for (nummodels=1 ; ; nummodels++)
386 str = MSG_ReadString ();
389 if (nummodels==MAX_MODELS)
391 Con_Printf ("Server sent too many model precaches\n");
394 if (strlen(str) >= MAX_QPATH)
395 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
396 strcpy (model_precache[nummodels], str);
397 Mod_TouchModel (str);
401 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
402 for (numsounds=1 ; ; numsounds++)
404 str = MSG_ReadString ();
407 if (numsounds==MAX_SOUNDS)
409 Con_Printf ("Server sent too many sound precaches\n");
412 if (strlen(str) >= MAX_QPATH)
413 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
414 strcpy (sound_precache[numsounds], str);
419 // now we try to load everything else until a cache allocation fails
422 for (i=1 ; i<nummodels ; i++)
424 isworldmodel = i == 1; // LordHavoc: first model is the world model
425 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
426 if (cl.model_precache[i] == NULL)
428 Con_Printf("Model %s not found\n", model_precache[i]);
431 CL_KeepaliveMessage ();
434 S_BeginPrecaching ();
435 for (i=1 ; i<numsounds ; i++)
437 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
438 CL_KeepaliveMessage ();
444 cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
448 Hunk_Check (); // make sure nothing is hurt
450 noclip_anglehack = false; // noclip is turned off at start
458 Parse an entity update message from the server
459 If an entities model or origin changes from frame to frame, it must be
460 relinked. Other attributes can change without relinking.
463 void CL_ParseUpdate (int bits)
465 int i, modnum, num, alpha, scale, glowsize, glowcolor, colormod, frame;
469 entity_state_t *baseline;
471 if (cls.signon == SIGNONS - 1)
472 { // first update is the final signon stage
473 cls.signon = SIGNONS;
477 if (bits & U_MOREBITS)
478 bits |= (MSG_ReadByte()<<8);
479 if (bits & U_EXTEND1 && !Nehahrademcompatibility)
481 bits |= MSG_ReadByte() << 16;
482 if (bits & U_EXTEND2)
483 bits |= MSG_ReadByte() << 24;
486 if (bits & U_LONGENTITY)
487 num = MSG_ReadShort ();
489 num = MSG_ReadByte ();
491 ent = CL_EntityNum (num);
493 forcelink = ent->msgtime != cl.mtime[1]; // no previous frame to lerp from
495 ent->msgtime = cl.mtime[0];
497 // LordHavoc: new protocol stuff
498 baseline = &ent->baseline;
500 baseline = &ent->deltabaseline;
504 ent->deltabaseline.origin[0] = ent->deltabaseline.origin[1] = ent->deltabaseline.origin[2] = 0;
505 ent->deltabaseline.angles[0] = ent->deltabaseline.angles[1] = ent->deltabaseline.angles[2] = 0;
506 ent->deltabaseline.effects = 0;
507 ent->deltabaseline.modelindex = 0;
508 ent->deltabaseline.frame = 0;
509 ent->deltabaseline.colormap = 0;
510 ent->deltabaseline.skin = 0;
511 ent->deltabaseline.alpha = 255;
512 ent->deltabaseline.scale = 16;
513 ent->deltabaseline.glowsize = 0;
514 ent->deltabaseline.glowcolor = 254;
515 ent->deltabaseline.colormod = 255;
518 modnum = bits & U_MODEL ? MSG_ReadByte() : baseline->modelindex;
519 if (modnum >= MAX_MODELS)
520 Host_Error ("CL_ParseModel: bad modnum");
522 frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF));
524 i = bits & U_COLORMAP ? MSG_ReadByte() : baseline->colormap;
525 ent->deltabaseline.colormap = i;
527 ent->colormap = -1; // no special coloring
530 if (i > cl.maxclients)
531 Host_Error ("i >= cl.maxclients");
532 ent->colormap = cl.scores[i-1].colors; // color it
535 ent->deltabaseline.skin = ent->skinnum = bits & U_SKIN ? MSG_ReadByte() : baseline->skin;
537 ent->effects = ((bits & U_EFFECTS) ? MSG_ReadByte() : (baseline->effects & 0xFF));
539 // shift the known values for interpolation
540 VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
541 VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
542 VectorCopy (baseline->origin, ent->msg_origins[0]);
543 VectorCopy (baseline->angles, ent->msg_angles[0]);
545 if (bits & U_ORIGIN1) ent->msg_origins[0][0] = MSG_ReadCoord ();
546 if (bits & U_ANGLE1) ent->msg_angles[0][0] = MSG_ReadAngle();
547 if (bits & U_ORIGIN2) ent->msg_origins[0][1] = MSG_ReadCoord ();
548 if (bits & U_ANGLE2) ent->msg_angles[0][1] = MSG_ReadAngle();
549 if (bits & U_ORIGIN3) ent->msg_origins[0][2] = MSG_ReadCoord ();
550 if (bits & U_ANGLE3) ent->msg_angles[0][2] = MSG_ReadAngle();
552 VectorCopy(ent->msg_origins[0], ent->deltabaseline.origin);
553 VectorCopy(ent->msg_angles[0], ent->deltabaseline.angles);
555 alpha = bits & U_ALPHA ? MSG_ReadByte() : baseline->alpha;
556 scale = bits & U_SCALE ? MSG_ReadByte() : baseline->scale;
557 ent->effects |= ((bits & U_EFFECTS2) ? (MSG_ReadByte() << 8) : (baseline->effects & 0xFF00));
558 glowsize = bits & U_GLOWSIZE ? MSG_ReadByte() : baseline->glowsize;
559 glowcolor = bits & U_GLOWCOLOR ? MSG_ReadByte() : baseline->glowcolor;
560 colormod = bits & U_COLORMOD ? MSG_ReadByte() : baseline->colormod;
561 modnum |= ((bits & U_MODEL2) ? (MSG_ReadByte() << 8) : (baseline->modelindex & 0xFF00));
562 frame |= ((bits & U_FRAME2) ? (MSG_ReadByte() << 8) : (baseline->frame & 0xFF00));
564 if (modnum >= MAX_MODELS)
565 Host_Error("modnum (%i) >= MAX_MODELS (%i)\n", modnum, MAX_MODELS);
567 model = cl.model_precache[modnum];
568 if (model != ent->model)
571 // automatic animation (torches, etc) can be either all together
574 ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;
576 forcelink = true; // hack to make null model players work
580 if (model && (unsigned) frame >= model->numframes)
581 Con_DPrintf("CL_ParseUpdate: no such frame %i in \"%s\"\n", frame, model->name);
583 ent->deltabaseline.alpha = alpha;
584 ent->deltabaseline.scale = scale;
585 ent->deltabaseline.effects = ent->effects;
586 ent->deltabaseline.glowsize = glowsize;
587 ent->deltabaseline.glowcolor = glowcolor;
588 ent->deltabaseline.colormod = colormod;
589 ent->deltabaseline.modelindex = modnum;
590 ent->deltabaseline.frame = frame;
591 ent->alpha = (float) alpha * (1.0 / 255.0);
592 ent->scale = (float) scale * (1.0 / 16.0);
593 ent->glowsize = glowsize * 4.0;
594 ent->glowcolor = glowcolor;
595 ent->colormod[0] = (float) ((colormod >> 5) & 7) * (1.0 / 7.0);
596 ent->colormod[1] = (float) ((colormod >> 2) & 7) * (1.0 / 7.0);
597 ent->colormod[2] = (float) (colormod & 3) * (1.0 / 3.0);
598 if (bits & U_EXTEND1 && Nehahrademcompatibility) // LordHavoc: to allow playback of the Nehahra movie
601 ent->alpha = MSG_ReadFloat();
602 if (i == 2 && MSG_ReadFloat() != 0.0)
603 ent->effects |= EF_FULLBRIGHT;
608 //if ( bits & U_NOLERP )
609 // ent->forcelink = true;
610 //if (bits & U_STEP) // FIXME: implement clientside interpolation of monsters
613 { // didn't have an update last message
614 VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
615 VectorCopy (ent->msg_origins[0], ent->origin);
616 VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
617 VectorCopy (ent->msg_angles[0], ent->angles);
618 ent->forcelink = true;
627 void CL_ParseBaseline (entity_t *ent, int largemodelindex)
632 ent->baseline.modelindex = (unsigned short) MSG_ReadShort ();
634 ent->baseline.modelindex = MSG_ReadByte ();
635 ent->baseline.frame = MSG_ReadByte ();
636 ent->baseline.colormap = MSG_ReadByte();
637 ent->baseline.skin = MSG_ReadByte();
638 for (i=0 ; i<3 ; i++)
640 ent->baseline.origin[i] = MSG_ReadCoord ();
641 ent->baseline.angles[i] = MSG_ReadAngle ();
643 ent->baseline.alpha = 255;
644 ent->baseline.scale = 16;
645 ent->baseline.glowsize = 0;
646 ent->baseline.glowcolor = 254;
647 ent->baseline.colormod = 255;
649 if (ent->baseline.modelindex >= MAX_MODELS)
650 Host_Error("CL_ParseBaseline: modelindex (%i) >= MAX_MODELS (%i)\n", ent->baseline.modelindex, MAX_MODELS);
658 Server information pertaining to this client only
661 void CL_ParseClientdata (int bits)
666 if (bits & SU_EXTEND1)
667 bits |= (MSG_ReadByte() << 16);
668 if (bits & SU_EXTEND2)
669 bits |= (MSG_ReadByte() << 24);
671 if (bits & SU_VIEWHEIGHT)
672 cl.viewheight = MSG_ReadChar ();
674 cl.viewheight = DEFAULT_VIEWHEIGHT;
676 if (bits & SU_IDEALPITCH)
677 cl.idealpitch = MSG_ReadChar ();
681 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
682 for (i=0 ; i<3 ; i++)
684 if (bits & (SU_PUNCH1<<i) )
687 cl.punchangle[i] = MSG_ReadPreciseAngle();
689 cl.punchangle[i] = MSG_ReadChar();
692 cl.punchangle[i] = 0;
693 if (bits & (SU_PUNCHVEC1<<i))
694 cl.punchvector[i] = MSG_ReadFloatCoord();
696 cl.punchvector[i] = 0;
697 if (bits & (SU_VELOCITY1<<i) )
698 cl.mvelocity[0][i] = MSG_ReadChar()*16;
700 cl.mvelocity[0][i] = 0;
706 for (j=0 ; j<32 ; j++)
707 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
708 cl.item_gettime[j] = cl.time;
712 cl.onground = (bits & SU_ONGROUND) != 0;
713 cl.inwater = (bits & SU_INWATER) != 0;
715 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
716 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
717 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
718 cl.stats[STAT_HEALTH] = MSG_ReadShort();
719 cl.stats[STAT_AMMO] = MSG_ReadByte();
721 cl.stats[STAT_SHELLS] = MSG_ReadByte();
722 cl.stats[STAT_NAILS] = MSG_ReadByte();
723 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
724 cl.stats[STAT_CELLS] = MSG_ReadByte();
729 cl.stats[STAT_ACTIVEWEAPON] = i;
731 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
735 =====================
737 =====================
739 void CL_ParseStatic (int largemodelindex)
745 if (i >= MAX_STATIC_ENTITIES)
746 Host_Error ("Too many static entities");
747 ent = &cl_static_entities[i];
749 CL_ParseBaseline (ent, largemodelindex);
751 // copy it to the current state
752 ent->model = cl.model_precache[ent->baseline.modelindex];
753 ent->frame = ent->frame1 = ent->frame2 = ent->baseline.frame;
755 ent->lerp_starttime = -1;
756 // make torchs play out of sync
757 ent->frame1start = ent->frame2start = -(rand() & 32767);
758 ent->colormap = -1; // no special coloring
759 ent->skinnum = ent->baseline.skin;
760 ent->effects = ent->baseline.effects;
765 ent->glowcolor = 254;
766 ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
768 VectorCopy (ent->baseline.origin, ent->origin);
769 VectorCopy (ent->baseline.angles, ent->angles);
778 void CL_ParseStaticSound (void)
781 int sound_num, vol, atten;
784 sound_num = MSG_ReadByte ();
785 vol = MSG_ReadByte ();
786 atten = MSG_ReadByte ();
788 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
791 void CL_ParseEffect (void)
794 int modelindex, startframe, framecount, framerate;
797 modelindex = MSG_ReadByte ();
798 startframe = MSG_ReadByte ();
799 framecount = MSG_ReadByte ();
800 framerate = MSG_ReadByte ();
802 CL_Effect(org, modelindex, startframe, framecount, framerate);
805 void CL_ParseEffect2 (void)
808 int modelindex, startframe, framecount, framerate;
811 modelindex = MSG_ReadShort ();
812 startframe = MSG_ReadByte ();
813 framecount = MSG_ReadByte ();
814 framerate = MSG_ReadByte ();
816 CL_Effect(org, modelindex, startframe, framecount, framerate);
820 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
822 extern void SHOWLMP_decodehide();
823 extern void SHOWLMP_decodeshow();
824 extern void R_SetSkyBox(char* sky);
828 =====================
829 CL_ParseServerMessage
830 =====================
832 void CL_ParseServerMessage (void)
837 char *cmdlogname[32], *temp;
838 int cmdindex, cmdcount = 0;
841 // if recording demos, copy the message out
843 if (cl_shownet.value == 1)
845 Con_Printf ("%i ",net_message.cursize);
848 else if (cl_shownet.value == 2)
850 Con_Printf ("------------------\n");
854 cl.onground = false; // unless the server says otherwise
863 Host_Error ("CL_ParseServerMessage: Bad server message");
865 cmd = MSG_ReadByte ();
869 SHOWNET("END OF MESSAGE");
870 return; // end of message
873 cmdindex = cmdcount & 31;
875 cmdlog[cmdindex] = cmd;
877 // if the high bit of the command byte is set, it is a fast update
880 // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
882 cmdlogname[cmdindex] = temp;
883 SHOWNET("fast update");
884 CL_ParseUpdate (cmd&127);
888 SHOWNET(svc_strings[cmd]);
889 cmdlogname[cmdindex] = svc_strings[cmd];
890 if (!cmdlogname[cmdindex])
892 // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
894 cmdlogname[cmdindex] = temp;
902 char description[32*64], temp[64];
904 strcpy(description, "packet dump: ");
908 count = cmdcount - i;
912 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
913 strcat(description, temp);
918 description[strlen(description)-1] = '\n'; // replace the last space with a newline
919 Con_Printf(description);
920 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
925 // Con_Printf ("svc_nop\n");
929 cl.mtime[1] = cl.mtime[0];
930 cl.mtime[0] = MSG_ReadFloat ();
934 i = MSG_ReadShort ();
935 CL_ParseClientdata (i);
940 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
942 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
945 Nehahrademcompatibility = false;
947 Nehahrademcompatibility = true;
948 if (cls.demoplayback && demo_nehahra.value)
949 Nehahrademcompatibility = true;
950 dpprotocol = i == DPPROTOCOL_VERSION;
954 Host_EndGame ("Server disconnected\n");
957 Con_Printf ("%s", MSG_ReadString ());
960 case svc_centerprint:
961 SCR_CenterPrint (MSG_ReadString ());
965 Cbuf_AddText (MSG_ReadString ());
973 CL_ParseServerInfo ();
974 vid.recalc_refdef = true; // leave intermission full screen
978 for (i=0 ; i<3 ; i++)
979 cl.viewangles[i] = MSG_ReadAngle ();
983 cl.viewentity = MSG_ReadShort ();
988 if (i >= MAX_LIGHTSTYLES)
989 Host_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
990 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
991 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
992 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
996 CL_ParseStartSoundPacket(false);
1000 CL_ParseStartSoundPacket(true);
1004 i = MSG_ReadShort();
1005 S_StopSound(i>>3, i&7);
1008 case svc_updatename:
1009 i = MSG_ReadByte ();
1010 if (i >= cl.maxclients)
1011 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1012 strcpy (cl.scores[i].name, MSG_ReadString ());
1015 case svc_updatefrags:
1016 i = MSG_ReadByte ();
1017 if (i >= cl.maxclients)
1018 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1019 cl.scores[i].frags = MSG_ReadShort ();
1022 case svc_updatecolors:
1023 i = MSG_ReadByte ();
1024 if (i >= cl.maxclients)
1025 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1026 cl.scores[i].colors = MSG_ReadByte ();
1030 R_ParseParticleEffect ();
1041 case svc_spawnbaseline:
1042 i = MSG_ReadShort ();
1043 // must use CL_EntityNum() to force cl.num_entities up
1044 CL_ParseBaseline (CL_EntityNum(i), false);
1046 case svc_spawnbaseline2:
1047 i = MSG_ReadShort ();
1048 // must use CL_EntityNum() to force cl.num_entities up
1049 CL_ParseBaseline (CL_EntityNum(i), false);
1051 case svc_spawnstatic:
1052 CL_ParseStatic (false);
1054 case svc_spawnstatic2:
1055 CL_ParseStatic (true);
1057 case svc_temp_entity:
1062 cl.paused = MSG_ReadByte ();
1070 i = MSG_ReadByte ();
1071 if (i <= cls.signon)
1072 Host_Error ("Received signon %i when at %i", i, cls.signon);
1077 case svc_killedmonster:
1078 cl.stats[STAT_MONSTERS]++;
1081 case svc_foundsecret:
1082 cl.stats[STAT_SECRETS]++;
1085 case svc_updatestat:
1086 i = MSG_ReadByte ();
1087 if (i < 0 || i >= MAX_CL_STATS)
1088 Host_Error ("svc_updatestat: %i is invalid", i);
1089 cl.stats[i] = MSG_ReadLong ();
1092 case svc_spawnstaticsound:
1093 CL_ParseStaticSound ();
1097 cl.cdtrack = MSG_ReadByte ();
1098 cl.looptrack = MSG_ReadByte ();
1099 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1100 CDAudio_Play ((byte)cls.forcetrack, true);
1102 CDAudio_Play ((byte)cl.cdtrack, true);
1105 case svc_intermission:
1106 cl.intermission = 1;
1107 cl.completed_time = cl.time;
1108 vid.recalc_refdef = true; // go to full screen
1112 cl.intermission = 2;
1113 cl.completed_time = cl.time;
1114 vid.recalc_refdef = true; // go to full screen
1115 SCR_CenterPrint (MSG_ReadString ());
1119 cl.intermission = 3;
1120 cl.completed_time = cl.time;
1121 vid.recalc_refdef = true; // go to full screen
1122 SCR_CenterPrint (MSG_ReadString ());
1125 case svc_sellscreen:
1126 Cmd_ExecuteString ("help", src_command);
1129 SHOWLMP_decodehide();
1132 SHOWLMP_decodeshow();