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);
827 =====================
828 CL_ParseServerMessage
829 =====================
831 void CL_ParseServerMessage (void)
836 char *cmdlogname[32], *temp;
837 int cmdindex, cmdcount = 0;
840 // if recording demos, copy the message out
842 if (cl_shownet.value == 1)
843 Con_Printf ("%i ",net_message.cursize);
844 else if (cl_shownet.value == 2)
845 Con_Printf ("------------------\n");
847 cl.onground = false; // unless the server says otherwise
856 Host_Error ("CL_ParseServerMessage: Bad server message");
858 cmd = MSG_ReadByte ();
862 SHOWNET("END OF MESSAGE");
863 return; // end of message
866 cmdindex = cmdcount & 31;
868 cmdlog[cmdindex] = cmd;
870 // if the high bit of the command byte is set, it is a fast update
873 // 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)
875 cmdlogname[cmdindex] = temp;
876 SHOWNET("fast update");
877 CL_ParseUpdate (cmd&127);
881 SHOWNET(svc_strings[cmd]);
882 cmdlogname[cmdindex] = svc_strings[cmd];
883 if (!cmdlogname[cmdindex])
885 // 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)
887 cmdlogname[cmdindex] = temp;
895 char description[32*64], temp[64];
897 strcpy(description, "packet dump: ");
901 count = cmdcount - i;
905 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
906 strcat(description, temp);
911 description[strlen(description)-1] = '\n'; // replace the last space with a newline
912 Con_Printf(description);
913 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
918 // Con_Printf ("svc_nop\n");
922 cl.mtime[1] = cl.mtime[0];
923 cl.mtime[0] = MSG_ReadFloat ();
927 i = MSG_ReadShort ();
928 CL_ParseClientdata (i);
933 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
935 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
938 Nehahrademcompatibility = false;
940 Nehahrademcompatibility = true;
941 if (cls.demoplayback && demo_nehahra.value)
942 Nehahrademcompatibility = true;
943 dpprotocol = i == DPPROTOCOL_VERSION;
947 Host_EndGame ("Server disconnected\n");
950 Con_Printf ("%s", MSG_ReadString ());
953 case svc_centerprint:
954 SCR_CenterPrint (MSG_ReadString ());
958 Cbuf_AddText (MSG_ReadString ());
966 CL_ParseServerInfo ();
967 vid.recalc_refdef = true; // leave intermission full screen
971 for (i=0 ; i<3 ; i++)
972 cl.viewangles[i] = MSG_ReadAngle ();
976 cl.viewentity = MSG_ReadShort ();
981 if (i >= MAX_LIGHTSTYLES)
982 Host_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
983 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
984 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
985 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
989 CL_ParseStartSoundPacket(false);
993 CL_ParseStartSoundPacket(true);
998 S_StopSound(i>>3, i&7);
1001 case svc_updatename:
1002 i = MSG_ReadByte ();
1003 if (i >= cl.maxclients)
1004 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1005 strcpy (cl.scores[i].name, MSG_ReadString ());
1008 case svc_updatefrags:
1009 i = MSG_ReadByte ();
1010 if (i >= cl.maxclients)
1011 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1012 cl.scores[i].frags = MSG_ReadShort ();
1015 case svc_updatecolors:
1016 i = MSG_ReadByte ();
1017 if (i >= cl.maxclients)
1018 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1019 cl.scores[i].colors = MSG_ReadByte ();
1023 R_ParseParticleEffect ();
1034 case svc_spawnbaseline:
1035 i = MSG_ReadShort ();
1036 // must use CL_EntityNum() to force cl.num_entities up
1037 CL_ParseBaseline (CL_EntityNum(i), false);
1039 case svc_spawnbaseline2:
1040 i = MSG_ReadShort ();
1041 // must use CL_EntityNum() to force cl.num_entities up
1042 CL_ParseBaseline (CL_EntityNum(i), false);
1044 case svc_spawnstatic:
1045 CL_ParseStatic (false);
1047 case svc_spawnstatic2:
1048 CL_ParseStatic (true);
1050 case svc_temp_entity:
1055 cl.paused = MSG_ReadByte ();
1063 i = MSG_ReadByte ();
1064 if (i <= cls.signon)
1065 Host_Error ("Received signon %i when at %i", i, cls.signon);
1070 case svc_killedmonster:
1071 cl.stats[STAT_MONSTERS]++;
1074 case svc_foundsecret:
1075 cl.stats[STAT_SECRETS]++;
1078 case svc_updatestat:
1079 i = MSG_ReadByte ();
1080 if (i < 0 || i >= MAX_CL_STATS)
1081 Host_Error ("svc_updatestat: %i is invalid", i);
1082 cl.stats[i] = MSG_ReadLong ();
1085 case svc_spawnstaticsound:
1086 CL_ParseStaticSound ();
1090 cl.cdtrack = MSG_ReadByte ();
1091 cl.looptrack = MSG_ReadByte ();
1092 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1093 CDAudio_Play ((byte)cls.forcetrack, true);
1095 CDAudio_Play ((byte)cl.cdtrack, true);
1098 case svc_intermission:
1099 cl.intermission = 1;
1100 cl.completed_time = cl.time;
1101 vid.recalc_refdef = true; // go to full screen
1105 cl.intermission = 2;
1106 cl.completed_time = cl.time;
1107 vid.recalc_refdef = true; // go to full screen
1108 SCR_CenterPrint (MSG_ReadString ());
1112 cl.intermission = 3;
1113 cl.completed_time = cl.time;
1114 vid.recalc_refdef = true; // go to full screen
1115 SCR_CenterPrint (MSG_ReadString ());
1118 case svc_sellscreen:
1119 Cmd_ExecuteString ("help", src_command);
1122 SHOWLMP_decodehide();
1125 SHOWLMP_decodeshow();