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