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
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 [byte] x [byte] y
69 "svc_hidelmp", // [string] iconlabel
70 "svc_skybox", // [string] skyname
83 "svc_farclip", // [coord] size
84 "svc_fog", // [byte] enable <optional past this point, only included if enable is true> [short * 4096] density [byte] red [byte] green [byte] blue
85 "svc_playerposition" // [float] x [float] y [float] z
88 //=============================================================================
90 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
91 qboolean dpprotocol; // LordHavoc: whether or not the current network stream is the enhanced DarkPlaces protocol
97 This error checks and tracks the total number of entities
100 entity_t *CL_EntityNum (int num)
102 if (num >= cl.num_entities)
104 if (num >= MAX_EDICTS)
105 Host_Error ("CL_EntityNum: %i is an invalid number",num);
106 while (cl.num_entities<=num)
108 cl_entities[cl.num_entities].colormap = -1; // no special coloring
113 return &cl_entities[num];
119 CL_ParseStartSoundPacket
122 void CL_ParseStartSoundPacket(void)
132 field_mask = MSG_ReadByte();
134 if (field_mask & SND_VOLUME)
135 volume = MSG_ReadByte ();
137 volume = DEFAULT_SOUND_PACKET_VOLUME;
139 if (field_mask & SND_ATTENUATION)
140 attenuation = MSG_ReadByte () / 64.0;
142 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
144 channel = MSG_ReadShort ();
145 sound_num = MSG_ReadByte ();
150 if (ent > MAX_EDICTS)
151 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
153 for (i=0 ; i<3 ; i++)
154 pos[i] = MSG_ReadCoord ();
156 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
163 When the client is taking a long time to load stuff, send keepalive messages
164 so the server doesn't disconnect.
167 void CL_KeepaliveMessage (void)
170 static float lastmsg;
176 return; // no need if server is local
177 if (cls.demoplayback)
180 // read messages from server, should just be nops
182 memcpy (olddata, net_message.data, net_message.cursize);
186 ret = CL_GetMessage ();
190 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
192 break; // nothing waiting
194 Host_Error ("CL_KeepaliveMessage: received a message");
197 if (MSG_ReadByte() != svc_nop)
198 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
204 memcpy (net_message.data, olddata, net_message.cursize);
207 time = Sys_FloatTime ();
208 if (time - lastmsg < 5)
213 Con_Printf ("--> client to server keepalive\n");
215 MSG_WriteByte (&cls.message, clc_nop);
216 NET_SendMessage (cls.netcon, &cls.message);
217 SZ_Clear (&cls.message);
220 extern qboolean isworldmodel;
221 extern char skyname[];
222 extern void R_SetSkyBox (char *sky);
223 extern void FOG_clear();
224 extern cvar_t r_farclip;
226 void CL_ParseEntityLump(char *entdata)
229 char key[128], value[1024];
232 FOG_clear(); // LordHavoc: no fog until set
233 skyname[0] = 0; // LordHavoc: no enviroment mapped sky until set
234 r_farclip.value = 6144; // LordHavoc: default farclip distance
238 data = COM_Parse(data);
240 return; // valid exit
241 if (com_token[0] != '{')
245 data = COM_Parse(data);
248 if (com_token[0] == '}')
249 return; // since we're just parsing the first ent (worldspawn), exit
250 strcpy(key, com_token);
251 while (key[strlen(key)-1] == ' ') // remove trailing spaces
252 key[strlen(key)-1] = 0;
253 data = COM_Parse(data);
256 strcpy(value, com_token);
257 if (!strcmp("sky", key))
259 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
261 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
263 else if (!strcmp("farclip", key))
265 r_farclip.value = atof(value);
266 if (r_farclip.value < 64)
267 r_farclip.value = 64;
269 else if (!strcmp("fog", key))
271 scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
274 else if (!strcmp("fog_density", key))
275 fog_density = atof(value);
276 else if (!strcmp("fog_red", key))
277 fog_red = atof(value);
278 else if (!strcmp("fog_green", key))
279 fog_green = atof(value);
280 else if (!strcmp("fog_blue", key))
281 fog_blue = atof(value);
282 else if (!strcmp("wad", key)) // for HalfLife maps
285 for (i = 0;i < 128;i++)
286 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
292 // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
293 if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
295 else if (value[i] == ';' || value[i] == 0)
299 strcpy(wadname, "textures/");
300 strcat(wadname, &value[j]);
301 W_LoadTextureWadFile (wadname, FALSE);
317 extern cvar_t demo_nehahra;
318 void CL_ParseServerInfo (void)
322 int nummodels, numsounds;
323 char model_precache[MAX_MODELS][MAX_QPATH];
324 char sound_precache[MAX_SOUNDS][MAX_QPATH];
326 Con_DPrintf ("Serverinfo packet received.\n");
328 // wipe the client_state_t struct
332 // parse protocol version number
334 if (i != PROTOCOL_VERSION && i != 250)
336 Con_Printf ("Server returned version %i, not %i", i, PROTOCOL_VERSION);
339 Nehahrademcompatibility = false;
341 Nehahrademcompatibility = true;
342 if (cls.demoplayback && demo_nehahra.value)
343 Nehahrademcompatibility = true;
344 dpprotocol = i == DPPROTOCOL_VERSION;
347 cl.maxclients = MSG_ReadByte ();
348 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
350 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
353 cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
356 cl.gametype = MSG_ReadByte ();
358 // parse signon message
359 str = MSG_ReadString ();
360 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
362 // seperate the printfs so the server message can have a color
363 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
365 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");
366 Con_Printf ("%c%s\n", 2, str);
370 // first we go through and touch all of the precache data that still
371 // happens to be in the cache, so precaching something else doesn't
372 // needlessly purge it
376 memset (cl.model_precache, 0, sizeof(cl.model_precache));
377 for (nummodels=1 ; ; nummodels++)
379 str = MSG_ReadString ();
382 if (nummodels==MAX_MODELS)
384 Con_Printf ("Server sent too many model precaches\n");
387 strcpy (model_precache[nummodels], str);
388 Mod_TouchModel (str);
392 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
393 for (numsounds=1 ; ; numsounds++)
395 str = MSG_ReadString ();
398 if (numsounds==MAX_SOUNDS)
400 Con_Printf ("Server sent too many sound precaches\n");
403 strcpy (sound_precache[numsounds], str);
408 // now we try to load everything else until a cache allocation fails
411 for (i=1 ; i<nummodels ; i++)
413 isworldmodel = i == 1; // LordHavoc: first model is the world model
414 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
415 if (cl.model_precache[i] == NULL)
417 Con_Printf("Model %s not found\n", model_precache[i]);
420 CL_KeepaliveMessage ();
423 S_BeginPrecaching ();
424 for (i=1 ; i<numsounds ; i++)
426 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
427 CL_KeepaliveMessage ();
433 cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
437 Hunk_Check (); // make sure nothing is hurt
439 noclip_anglehack = false; // noclip is turned off at start
447 Parse an entity update message from the server
448 If an entities model or origin changes from frame to frame, it must be
449 relinked. Other attributes can change without relinking.
452 void CL_ParseUpdate (int bits)
454 int i, modnum, num, alpha, scale, glowsize, glowcolor, colormod;
458 entity_state_t *baseline;
460 if (cls.signon == SIGNONS - 1)
461 { // first update is the final signon stage
462 cls.signon = SIGNONS;
466 if (bits & U_MOREBITS)
467 bits |= (MSG_ReadByte()<<8);
468 if (bits & U_EXTEND1 && !Nehahrademcompatibility)
470 bits |= MSG_ReadByte() << 16;
471 if (bits & U_EXTEND2)
472 bits |= MSG_ReadByte() << 24;
475 if (bits & U_LONGENTITY)
476 num = MSG_ReadShort ();
478 num = MSG_ReadByte ();
480 ent = CL_EntityNum (num);
482 forcelink = ent->msgtime != cl.mtime[1]; // no previous frame to lerp from
484 ent->msgtime = cl.mtime[0];
486 // LordHavoc: new protocol stuff
487 baseline = &ent->baseline;
489 baseline = &ent->deltabaseline;
493 ent->deltabaseline.origin[0] = ent->deltabaseline.origin[1] = ent->deltabaseline.origin[2] = 0;
494 ent->deltabaseline.angles[0] = ent->deltabaseline.angles[1] = ent->deltabaseline.angles[2] = 0;
495 ent->deltabaseline.effects = 0;
496 ent->deltabaseline.modelindex = 0;
497 ent->deltabaseline.frame = 0;
498 ent->deltabaseline.colormap = 0;
499 ent->deltabaseline.skin = 0;
500 ent->deltabaseline.alpha = 255;
501 ent->deltabaseline.scale = 16;
502 ent->deltabaseline.glowsize = 0;
503 ent->deltabaseline.glowcolor = 254;
504 ent->deltabaseline.colormod = 255;
507 modnum = bits & U_MODEL ? MSG_ReadByte() : baseline->modelindex;
508 if (modnum >= MAX_MODELS)
509 Host_Error ("CL_ParseModel: bad modnum");
510 ent->deltabaseline.modelindex = modnum;
512 model = cl.model_precache[modnum];
513 if (model != ent->model)
516 // automatic animation (torches, etc) can be either all together
519 ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;
521 forcelink = true; // hack to make null model players work
524 ent->frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF));
526 i = bits & U_COLORMAP ? MSG_ReadByte() : baseline->colormap;
527 ent->deltabaseline.colormap = i;
529 ent->colormap = -1; // no special coloring
532 if (i > cl.maxclients)
533 Host_Error ("i >= cl.maxclients");
534 ent->colormap = cl.scores[i-1].colors; // color it
537 ent->deltabaseline.skin = ent->skinnum = bits & U_SKIN ? MSG_ReadByte() : baseline->skin;
539 ent->effects = ((bits & U_EFFECTS) ? MSG_ReadByte() : (baseline->effects & 0xFF));
541 // shift the known values for interpolation
542 VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
543 VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
544 VectorCopy (baseline->origin, ent->msg_origins[0]);
545 VectorCopy (baseline->angles, ent->msg_angles[0]);
547 if (bits & U_ORIGIN1) ent->msg_origins[0][0] = MSG_ReadCoord ();
548 if (bits & U_ANGLE1) ent->msg_angles[0][0] = MSG_ReadAngle();
549 if (bits & U_ORIGIN2) ent->msg_origins[0][1] = MSG_ReadCoord ();
550 if (bits & U_ANGLE2) ent->msg_angles[0][1] = MSG_ReadAngle();
551 if (bits & U_ORIGIN3) ent->msg_origins[0][2] = MSG_ReadCoord ();
552 if (bits & U_ANGLE3) ent->msg_angles[0][2] = MSG_ReadAngle();
554 VectorCopy(ent->msg_origins[0], ent->deltabaseline.origin);
555 VectorCopy(ent->msg_angles[0], ent->deltabaseline.angles);
557 alpha = bits & U_ALPHA ? MSG_ReadByte() : baseline->alpha;
558 scale = bits & U_SCALE ? MSG_ReadByte() : baseline->scale;
559 ent->effects |= ((bits & U_EFFECTS2) ? (MSG_ReadByte() << 8) : (baseline->effects & 0xFF00));
560 glowsize = bits & U_GLOWSIZE ? MSG_ReadByte() : baseline->glowsize;
561 glowcolor = bits & U_GLOWCOLOR ? MSG_ReadByte() : baseline->glowcolor;
562 colormod = bits & U_COLORMOD ? MSG_ReadByte() : baseline->colormod;
563 ent->frame |= ((bits & U_FRAME2) ? (MSG_ReadByte() << 8) : (baseline->frame & 0xFF00));
564 ent->deltabaseline.alpha = alpha;
565 ent->deltabaseline.scale = scale;
566 ent->deltabaseline.effects = ent->effects;
567 ent->deltabaseline.glowsize = glowsize;
568 ent->deltabaseline.glowcolor = glowcolor;
569 ent->deltabaseline.colormod = colormod;
570 ent->deltabaseline.frame = ent->frame;
571 ent->alpha = (float) alpha * (1.0 / 255.0);
572 ent->scale = (float) scale * (1.0 / 16.0);
573 ent->glowsize = glowsize * 4.0;
574 ent->glowcolor = glowcolor;
575 ent->colormod[0] = (float) ((colormod >> 5) & 7) * (1.0 / 7.0);
576 ent->colormod[1] = (float) ((colormod >> 2) & 7) * (1.0 / 7.0);
577 ent->colormod[2] = (float) (colormod & 3) * (1.0 / 3.0);
578 if (bits & U_EXTEND1 && Nehahrademcompatibility) // LordHavoc: to allow playback of the early Nehahra movie segments
581 ent->alpha = MSG_ReadFloat();
582 if (i == 2 && MSG_ReadFloat() != 0.0)
583 ent->effects |= EF_FULLBRIGHT;
588 //if ( bits & U_NOLERP )
589 // ent->forcelink = true;
590 //if (bits & U_STEP) // FIXME: implement clientside interpolation of monsters
593 { // didn't have an update last message
594 VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
595 VectorCopy (ent->msg_origins[0], ent->origin);
596 VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
597 VectorCopy (ent->msg_angles[0], ent->angles);
598 ent->forcelink = true;
607 void CL_ParseBaseline (entity_t *ent)
611 ent->baseline.modelindex = MSG_ReadByte ();
612 ent->baseline.frame = MSG_ReadByte ();
613 ent->baseline.colormap = MSG_ReadByte();
614 ent->baseline.skin = MSG_ReadByte();
615 for (i=0 ; i<3 ; i++)
617 ent->baseline.origin[i] = MSG_ReadCoord ();
618 ent->baseline.angles[i] = MSG_ReadAngle ();
620 ent->baseline.alpha = 255;
621 ent->baseline.scale = 16;
622 ent->baseline.glowsize = 0;
623 ent->baseline.glowcolor = 254;
624 ent->baseline.colormod = 255;
632 Server information pertaining to this client only
635 void CL_ParseClientdata (int bits)
639 if (bits & SU_VIEWHEIGHT)
640 cl.viewheight = MSG_ReadChar ();
642 cl.viewheight = DEFAULT_VIEWHEIGHT;
644 if (bits & SU_IDEALPITCH)
645 cl.idealpitch = MSG_ReadChar ();
649 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
650 for (i=0 ; i<3 ; i++)
652 if (bits & (SU_PUNCH1<<i) )
653 cl.punchangle[i] = MSG_ReadChar();
655 cl.punchangle[i] = 0;
656 if (bits & (SU_VELOCITY1<<i) )
657 cl.mvelocity[0][i] = MSG_ReadChar()*16;
659 cl.mvelocity[0][i] = 0;
665 for (j=0 ; j<32 ; j++)
666 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
667 cl.item_gettime[j] = cl.time;
671 cl.onground = (bits & SU_ONGROUND) != 0;
672 cl.inwater = (bits & SU_INWATER) != 0;
674 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
675 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
676 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
677 cl.stats[STAT_HEALTH] = MSG_ReadShort();
678 cl.stats[STAT_AMMO] = MSG_ReadByte();
680 cl.stats[STAT_SHELLS] = MSG_ReadByte();
681 cl.stats[STAT_NAILS] = MSG_ReadByte();
682 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
683 cl.stats[STAT_CELLS] = MSG_ReadByte();
688 cl.stats[STAT_ACTIVEWEAPON] = i;
690 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
694 =====================
696 =====================
698 void CL_ParseStatic (void)
704 if (i >= MAX_STATIC_ENTITIES)
705 Host_Error ("Too many static entities");
706 ent = &cl_static_entities[i];
708 CL_ParseBaseline (ent);
710 // copy it to the current state
711 ent->model = cl.model_precache[ent->baseline.modelindex];
712 ent->frame = ent->baseline.frame;
713 ent->colormap = -1; // no special coloring
714 ent->skinnum = ent->baseline.skin;
715 ent->effects = ent->baseline.effects;
720 ent->glowcolor = 254;
721 ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
723 VectorCopy (ent->baseline.origin, ent->origin);
724 VectorCopy (ent->baseline.angles, ent->angles);
733 void CL_ParseStaticSound (void)
736 int sound_num, vol, atten;
739 for (i=0 ; i<3 ; i++)
740 org[i] = MSG_ReadCoord ();
741 sound_num = MSG_ReadByte ();
742 vol = MSG_ReadByte ();
743 atten = MSG_ReadByte ();
745 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
749 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
751 extern void SHOWLMP_decodehide();
752 extern void SHOWLMP_decodeshow();
753 extern void R_SetSkyBox(char* sky);
756 =====================
757 CL_ParseServerMessage
758 =====================
760 void CL_ParseServerMessage (void)
766 // if recording demos, copy the message out
768 if (cl_shownet.value == 1)
769 Con_Printf ("%i ",net_message.cursize);
770 else if (cl_shownet.value == 2)
771 Con_Printf ("------------------\n");
773 cl.onground = false; // unless the server says otherwise
782 Host_Error ("CL_ParseServerMessage: Bad server message");
784 cmd = MSG_ReadByte ();
788 SHOWNET("END OF MESSAGE");
789 return; // end of message
792 // if the high bit of the command byte is set, it is a fast update
795 SHOWNET("fast update");
796 CL_ParseUpdate (cmd&127);
800 SHOWNET(svc_strings[cmd]);
806 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
810 // Con_Printf ("svc_nop\n");
814 cl.mtime[1] = cl.mtime[0];
815 cl.mtime[0] = MSG_ReadFloat ();
819 i = MSG_ReadShort ();
820 CL_ParseClientdata (i);
825 if (i != PROTOCOL_VERSION && i != 250)
826 Host_Error ("CL_ParseServerMessage: Server is protocol %i instead of %i\n", i, PROTOCOL_VERSION);
827 Nehahrademcompatibility = i == 250;
831 Host_EndGame ("Server disconnected\n");
834 Con_Printf ("%s", MSG_ReadString ());
837 case svc_centerprint:
838 SCR_CenterPrint (MSG_ReadString ());
842 Cbuf_AddText (MSG_ReadString ());
850 CL_ParseServerInfo ();
851 vid.recalc_refdef = true; // leave intermission full screen
855 for (i=0 ; i<3 ; i++)
856 cl.viewangles[i] = MSG_ReadAngle ();
860 cl.viewentity = MSG_ReadShort ();
865 if (i >= MAX_LIGHTSTYLES)
866 Host_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
867 strcpy (cl_lightstyle[i].map, MSG_ReadString());
868 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
872 CL_ParseStartSoundPacket();
877 S_StopSound(i>>3, i&7);
882 if (i >= cl.maxclients)
883 Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD");
884 strcpy (cl.scores[i].name, MSG_ReadString ());
887 case svc_updatefrags:
889 if (i >= cl.maxclients)
890 Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD");
891 cl.scores[i].frags = MSG_ReadShort ();
894 case svc_updatecolors:
896 if (i >= cl.maxclients)
897 Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
898 cl.scores[i].colors = MSG_ReadByte ();
902 R_ParseParticleEffect ();
905 case svc_spawnbaseline:
906 i = MSG_ReadShort ();
907 // must use CL_EntityNum() to force cl.num_entities up
908 CL_ParseBaseline (CL_EntityNum(i));
910 case svc_spawnstatic:
913 case svc_temp_entity:
919 cl.paused = MSG_ReadByte ();
931 Host_Error ("Received signon %i when at %i", i, cls.signon);
936 case svc_killedmonster:
937 cl.stats[STAT_MONSTERS]++;
940 case svc_foundsecret:
941 cl.stats[STAT_SECRETS]++;
946 if (i < 0 || i >= MAX_CL_STATS)
947 Host_Error ("svc_updatestat: %i is invalid", i);
948 cl.stats[i] = MSG_ReadLong ();;
951 case svc_spawnstaticsound:
952 CL_ParseStaticSound ();
956 cl.cdtrack = MSG_ReadByte ();
957 cl.looptrack = MSG_ReadByte ();
958 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
959 CDAudio_Play ((byte)cls.forcetrack, true);
961 CDAudio_Play ((byte)cl.cdtrack, true);
964 case svc_intermission:
966 cl.completed_time = cl.time;
967 vid.recalc_refdef = true; // go to full screen
972 cl.completed_time = cl.time;
973 vid.recalc_refdef = true; // go to full screen
974 SCR_CenterPrint (MSG_ReadString ());
979 cl.completed_time = cl.time;
980 vid.recalc_refdef = true; // go to full screen
981 SCR_CenterPrint (MSG_ReadString ());
985 Cmd_ExecuteString ("help", src_command);
988 SHOWLMP_decodehide();
991 SHOWLMP_decodeshow();
993 // LordHavoc: extra worldspawn fields (fog, sky, farclip)
995 R_SetSkyBox(MSG_ReadString());
998 r_farclip.value = MSG_ReadCoord();
1003 fog_density = MSG_ReadShort() * (1.0f / 4096.0f);
1004 fog_red = MSG_ReadByte() * (1.0 / 255.0);
1005 fog_green = MSG_ReadByte() * (1.0 / 255.0);
1006 fog_blue = MSG_ReadByte() * (1.0 / 255.0);