bmodel rotation physics now work
[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 = -1; // no special coloring
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 void R_SetSkyBox (char *sky);
223 extern void FOG_clear();
224 extern cvar_t r_farclip;
225
226 void CL_ParseEntityLump(char *entdata)
227 {
228         char *data;
229         char key[128], value[1024];
230         char wadname[128];
231         int i, j, k;
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
235         data = entdata;
236         if (!data)
237                 return;
238         data = COM_Parse(data);
239         if (!data)
240                 return; // valid exit
241         if (com_token[0] != '{')
242                 return; // error
243         while (1)
244         {
245                 data = COM_Parse(data);
246                 if (!data)
247                         return; // error
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);
254                 if (!data)
255                         return; // error
256                 strcpy(value, com_token);
257                 if (!strcmp("sky", key))
258                         R_SetSkyBox(value);
259                 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
260                         R_SetSkyBox(value);
261                 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
262                         R_SetSkyBox(value);
263                 else if (!strcmp("farclip", key))
264                 {
265                         r_farclip.value = atof(value);
266                         if (r_farclip.value < 64)
267                                 r_farclip.value = 64;
268                 }
269                 else if (!strcmp("fog", key))
270                 {
271                         scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
272                         j = 0;
273                 }
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
283                 {
284                         j = 0;
285                         for (i = 0;i < 128;i++)
286                                 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
287                                         break;
288                         if (value[i])
289                         {
290                                 for (;i < 128;i++)
291                                 {
292                                         // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
293                                         if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
294                                                 j = i+1;
295                                         else if (value[i] == ';' || value[i] == 0)
296                                         {
297                                                 k = value[i];
298                                                 value[i] = 0;
299                                                 strcpy(wadname, "textures/");
300                                                 strcat(wadname, &value[j]);
301                                                 W_LoadTextureWadFile (wadname, FALSE);
302                                                 j = i+1;
303                                                 if (!k)
304                                                         break;
305                                         }
306                                 }
307                         }
308                 }
309         }
310 }
311
312 /*
313 ==================
314 CL_ParseServerInfo
315 ==================
316 */
317 extern cvar_t demo_nehahra;
318 void CL_ParseServerInfo (void)
319 {
320         char    *str;
321         int             i;
322         int             nummodels, numsounds;
323         char    model_precache[MAX_MODELS][MAX_QPATH];
324         char    sound_precache[MAX_SOUNDS][MAX_QPATH];
325         
326         Con_DPrintf ("Serverinfo packet received.\n");
327 //
328 // wipe the client_state_t struct
329 //
330         CL_ClearState ();
331
332 // parse protocol version number
333         i = MSG_ReadLong ();
334         if (i != PROTOCOL_VERSION && i != 250)
335         {
336                 Con_Printf ("Server returned version %i, not %i", i, PROTOCOL_VERSION);
337                 return;
338         }
339         Nehahrademcompatibility = false;
340         if (i == 250)
341                 Nehahrademcompatibility = true;
342         if (cls.demoplayback && demo_nehahra.value)
343                 Nehahrademcompatibility = true;
344         dpprotocol = i == DPPROTOCOL_VERSION;
345
346 // parse maxclients
347         cl.maxclients = MSG_ReadByte ();
348         if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
349         {
350                 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
351                 return;
352         }
353         cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
354
355 // parse gametype
356         cl.gametype = MSG_ReadByte ();
357
358 // parse signon message
359         str = MSG_ReadString ();
360         strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
361
362 // seperate the printfs so the server message can have a color
363         if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
364         {
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);
367         }
368
369 //
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
373 //
374
375 // precache models
376         memset (cl.model_precache, 0, sizeof(cl.model_precache));
377         for (nummodels=1 ; ; nummodels++)
378         {
379                 str = MSG_ReadString ();
380                 if (!str[0])
381                         break;
382                 if (nummodels==MAX_MODELS)
383                 {
384                         Con_Printf ("Server sent too many model precaches\n");
385                         return;
386                 }
387                 strcpy (model_precache[nummodels], str);
388                 Mod_TouchModel (str);
389         }
390
391 // precache sounds
392         memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
393         for (numsounds=1 ; ; numsounds++)
394         {
395                 str = MSG_ReadString ();
396                 if (!str[0])
397                         break;
398                 if (numsounds==MAX_SOUNDS)
399                 {
400                         Con_Printf ("Server sent too many sound precaches\n");
401                         return;
402                 }
403                 strcpy (sound_precache[numsounds], str);
404                 S_TouchSound (str);
405         }
406
407 //
408 // now we try to load everything else until a cache allocation fails
409 //
410
411         for (i=1 ; i<nummodels ; i++)
412         {
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)
416                 {
417                         Con_Printf("Model %s not found\n", model_precache[i]);
418                         return;
419                 }
420                 CL_KeepaliveMessage ();
421         }
422
423         S_BeginPrecaching ();
424         for (i=1 ; i<numsounds ; i++)
425         {
426                 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
427                 CL_KeepaliveMessage ();
428         }
429         S_EndPrecaching ();
430
431
432 // local state
433         cl_entities[0].model = cl.worldmodel = cl.model_precache[1];
434         
435         R_NewMap ();
436
437         Hunk_Check ();          // make sure nothing is hurt
438         
439         noclip_anglehack = false;               // noclip is turned off at start        
440 }
441
442
443 /*
444 ==================
445 CL_ParseUpdate
446
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.
450 ==================
451 */
452 void CL_ParseUpdate (int bits)
453 {
454         int                     i, modnum, num, alpha, scale, glowsize, glowcolor, colormod;
455         model_t         *model;
456         qboolean        forcelink;
457         entity_t        *ent;
458         entity_state_t *baseline;
459
460         if (cls.signon == SIGNONS - 1)
461         {       // first update is the final signon stage
462                 cls.signon = SIGNONS;
463                 CL_SignonReply ();
464         }
465
466         if (bits & U_MOREBITS)
467                 bits |= (MSG_ReadByte()<<8);
468         if (bits & U_EXTEND1 && !Nehahrademcompatibility)
469         {
470                 bits |= MSG_ReadByte() << 16;
471                 if (bits & U_EXTEND2)
472                         bits |= MSG_ReadByte() << 24;
473         }
474
475         if (bits & U_LONGENTITY)        
476                 num = MSG_ReadShort ();
477         else
478                 num = MSG_ReadByte ();
479
480         ent = CL_EntityNum (num);
481
482         forcelink = ent->msgtime != cl.mtime[1]; // no previous frame to lerp from
483
484         ent->msgtime = cl.mtime[0];
485         
486         // LordHavoc: new protocol stuff
487         baseline = &ent->baseline;
488         if (bits & U_DELTA)
489                 baseline = &ent->deltabaseline;
490
491         if (forcelink)
492         {
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;
505         }
506
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;
511                 
512         model = cl.model_precache[modnum];
513         if (model != ent->model)
514         {
515                 ent->model = model;
516         // automatic animation (torches, etc) can be either all together
517         // or randomized
518                 if (model)
519                         ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;
520                 else
521                         forcelink = true;       // hack to make null model players work
522         }
523
524         ent->frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF));
525
526         i = bits & U_COLORMAP ? MSG_ReadByte() : baseline->colormap;
527         ent->deltabaseline.colormap = i;
528         if (!i)
529                 ent->colormap = -1; // no special coloring
530         else
531         {
532                 if (i > cl.maxclients)
533                         Host_Error ("i >= cl.maxclients");
534                 ent->colormap = cl.scores[i-1].colors; // color it
535         }
536
537         ent->deltabaseline.skin = ent->skinnum = bits & U_SKIN ? MSG_ReadByte() : baseline->skin;
538
539         ent->effects = ((bits & U_EFFECTS) ? MSG_ReadByte() : (baseline->effects & 0xFF));
540
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]);
546
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();
553
554         VectorCopy(ent->msg_origins[0], ent->deltabaseline.origin);
555         VectorCopy(ent->msg_angles[0], ent->deltabaseline.angles);
556
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
579         {
580                 i = MSG_ReadFloat();
581                 ent->alpha = MSG_ReadFloat();
582                 if (i == 2 && MSG_ReadFloat() != 0.0)
583                         ent->effects |= EF_FULLBRIGHT;
584                 if (ent->alpha == 0)
585                         ent->alpha = 1;
586         }
587
588         //if ( bits & U_NOLERP )
589         //      ent->forcelink = true;
590         //if (bits & U_STEP) // FIXME: implement clientside interpolation of monsters
591
592         if ( forcelink )
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;
599         }
600 }
601
602 /*
603 ==================
604 CL_ParseBaseline
605 ==================
606 */
607 void CL_ParseBaseline (entity_t *ent)
608 {
609         int                     i;
610         
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++)
616         {
617                 ent->baseline.origin[i] = MSG_ReadCoord ();
618                 ent->baseline.angles[i] = MSG_ReadAngle ();
619         }
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;
625 }
626
627
628 /*
629 ==================
630 CL_ParseClientdata
631
632 Server information pertaining to this client only
633 ==================
634 */
635 void CL_ParseClientdata (int bits)
636 {
637         int             i, j;
638         
639         if (bits & SU_VIEWHEIGHT)
640                 cl.viewheight = MSG_ReadChar ();
641         else
642                 cl.viewheight = DEFAULT_VIEWHEIGHT;
643
644         if (bits & SU_IDEALPITCH)
645                 cl.idealpitch = MSG_ReadChar ();
646         else
647                 cl.idealpitch = 0;
648         
649         VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
650         for (i=0 ; i<3 ; i++)
651         {
652                 if (bits & (SU_PUNCH1<<i) )
653                         cl.punchangle[i] = MSG_ReadChar();
654                 else
655                         cl.punchangle[i] = 0;
656                 if (bits & (SU_VELOCITY1<<i) )
657                         cl.mvelocity[0][i] = MSG_ReadChar()*16;
658                 else
659                         cl.mvelocity[0][i] = 0;
660         }
661
662         i = MSG_ReadLong ();
663         if (cl.items != i)
664         {       // set flash times
665                 for (j=0 ; j<32 ; j++)
666                         if ( (i & (1<<j)) && !(cl.items & (1<<j)))
667                                 cl.item_gettime[j] = cl.time;
668                 cl.items = i;
669         }
670                 
671         cl.onground = (bits & SU_ONGROUND) != 0;
672         cl.inwater = (bits & SU_INWATER) != 0;
673
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();
679
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();
684
685         i = MSG_ReadByte ();
686
687         if (standard_quake)
688                 cl.stats[STAT_ACTIVEWEAPON] = i;
689         else
690                 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
691 }
692
693 /*
694 =====================
695 CL_ParseStatic
696 =====================
697 */
698 void CL_ParseStatic (void)
699 {
700         entity_t *ent;
701         int             i;
702                 
703         i = cl.num_statics;
704         if (i >= MAX_STATIC_ENTITIES)
705                 Host_Error ("Too many static entities");
706         ent = &cl_static_entities[i];
707         cl.num_statics++;
708         CL_ParseBaseline (ent);
709
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;
716         ent->alpha = 1;
717         ent->scale = 1;
718         ent->alpha = 1;
719         ent->glowsize = 0;
720         ent->glowcolor = 254;
721         ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
722
723         VectorCopy (ent->baseline.origin, ent->origin);
724         VectorCopy (ent->baseline.angles, ent->angles); 
725         R_AddEfrags (ent);
726 }
727
728 /*
729 ===================
730 CL_ParseStaticSound
731 ===================
732 */
733 void CL_ParseStaticSound (void)
734 {
735         vec3_t          org;
736         int                     sound_num, vol, atten;
737         int                     i;
738         
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 ();
744         
745         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
746 }
747
748
749 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
750
751 extern void SHOWLMP_decodehide();
752 extern void SHOWLMP_decodeshow();
753 extern void R_SetSkyBox(char* sky);
754
755 /*
756 =====================
757 CL_ParseServerMessage
758 =====================
759 */
760 void CL_ParseServerMessage (void)
761 {
762         int                     cmd;
763         int                     i;
764         
765 //
766 // if recording demos, copy the message out
767 //
768         if (cl_shownet.value == 1)
769                 Con_Printf ("%i ",net_message.cursize);
770         else if (cl_shownet.value == 2)
771                 Con_Printf ("------------------\n");
772         
773         cl.onground = false;    // unless the server says otherwise     
774 //
775 // parse the message
776 //
777         MSG_BeginReading ();
778         
779         while (1)
780         {
781                 if (msg_badread)
782                         Host_Error ("CL_ParseServerMessage: Bad server message");
783
784                 cmd = MSG_ReadByte ();
785
786                 if (cmd == -1)
787                 {
788                         SHOWNET("END OF MESSAGE");
789                         return;         // end of message
790                 }
791
792         // if the high bit of the command byte is set, it is a fast update
793                 if (cmd & 128)
794                 {
795                         SHOWNET("fast update");
796                         CL_ParseUpdate (cmd&127);
797                         continue;
798                 }
799
800                 SHOWNET(svc_strings[cmd]);
801         
802         // other commands
803                 switch (cmd)
804                 {
805                 default:
806                         Host_Error ("CL_ParseServerMessage: Illegible server message\n");
807                         break;
808                         
809                 case svc_nop:
810 //                      Con_Printf ("svc_nop\n");
811                         break;
812                         
813                 case svc_time:
814                         cl.mtime[1] = cl.mtime[0];
815                         cl.mtime[0] = MSG_ReadFloat ();                 
816                         break;
817                         
818                 case svc_clientdata:
819                         i = MSG_ReadShort ();
820                         CL_ParseClientdata (i);
821                         break;
822                 
823                 case svc_version:
824                         i = MSG_ReadLong ();
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;
828                         break;
829                         
830                 case svc_disconnect:
831                         Host_EndGame ("Server disconnected\n");
832
833                 case svc_print:
834                         Con_Printf ("%s", MSG_ReadString ());
835                         break;
836                         
837                 case svc_centerprint:
838                         SCR_CenterPrint (MSG_ReadString ());
839                         break;
840                         
841                 case svc_stufftext:
842                         Cbuf_AddText (MSG_ReadString ());
843                         break;
844                         
845                 case svc_damage:
846                         V_ParseDamage ();
847                         break;
848                         
849                 case svc_serverinfo:
850                         CL_ParseServerInfo ();
851                         vid.recalc_refdef = true;       // leave intermission full screen
852                         break;
853                         
854                 case svc_setangle:
855                         for (i=0 ; i<3 ; i++)
856                                 cl.viewangles[i] = MSG_ReadAngle ();
857                         break;
858                         
859                 case svc_setview:
860                         cl.viewentity = MSG_ReadShort ();
861                         break;
862                                         
863                 case svc_lightstyle:
864                         i = MSG_ReadByte ();
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);
869                         break;
870                         
871                 case svc_sound:
872                         CL_ParseStartSoundPacket();
873                         break;
874                         
875                 case svc_stopsound:
876                         i = MSG_ReadShort();
877                         S_StopSound(i>>3, i&7);
878                         break;
879                 
880                 case svc_updatename:
881                         i = MSG_ReadByte ();
882                         if (i >= cl.maxclients)
883                                 Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD");
884                         strcpy (cl.scores[i].name, MSG_ReadString ());
885                         break;
886                         
887                 case svc_updatefrags:
888                         i = MSG_ReadByte ();
889                         if (i >= cl.maxclients)
890                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD");
891                         cl.scores[i].frags = MSG_ReadShort ();
892                         break;                  
893
894                 case svc_updatecolors:
895                         i = MSG_ReadByte ();
896                         if (i >= cl.maxclients)
897                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
898                         cl.scores[i].colors = MSG_ReadByte ();
899                         break;
900                         
901                 case svc_particle:
902                         R_ParseParticleEffect ();
903                         break;
904
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));
909                         break;
910                 case svc_spawnstatic:
911                         CL_ParseStatic ();
912                         break;                  
913                 case svc_temp_entity:
914                         CL_ParseTEnt ();
915                         break;
916
917                 case svc_setpause:
918                         {
919                                 cl.paused = MSG_ReadByte ();
920
921                                 if (cl.paused)
922                                         CDAudio_Pause ();
923                                 else
924                                         CDAudio_Resume ();
925                         }
926                         break;
927                         
928                 case svc_signonnum:
929                         i = MSG_ReadByte ();
930                         if (i <= cls.signon)
931                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
932                         cls.signon = i;
933                         CL_SignonReply ();
934                         break;
935
936                 case svc_killedmonster:
937                         cl.stats[STAT_MONSTERS]++;
938                         break;
939
940                 case svc_foundsecret:
941                         cl.stats[STAT_SECRETS]++;
942                         break;
943
944                 case svc_updatestat:
945                         i = MSG_ReadByte ();
946                         if (i < 0 || i >= MAX_CL_STATS)
947                                 Host_Error ("svc_updatestat: %i is invalid", i);
948                         cl.stats[i] = MSG_ReadLong ();;
949                         break;
950                         
951                 case svc_spawnstaticsound:
952                         CL_ParseStaticSound ();
953                         break;
954
955                 case svc_cdtrack:
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);
960                         else
961                                 CDAudio_Play ((byte)cl.cdtrack, true);
962                         break;
963
964                 case svc_intermission:
965                         cl.intermission = 1;
966                         cl.completed_time = cl.time;
967                         vid.recalc_refdef = true;       // go to full screen
968                         break;
969
970                 case svc_finale:
971                         cl.intermission = 2;
972                         cl.completed_time = cl.time;
973                         vid.recalc_refdef = true;       // go to full screen
974                         SCR_CenterPrint (MSG_ReadString ());                    
975                         break;
976
977                 case svc_cutscene:
978                         cl.intermission = 3;
979                         cl.completed_time = cl.time;
980                         vid.recalc_refdef = true;       // go to full screen
981                         SCR_CenterPrint (MSG_ReadString ());                    
982                         break;
983
984                 case svc_sellscreen:
985                         Cmd_ExecuteString ("help", src_command);
986                         break;
987                 case svc_hidelmp:
988                         SHOWLMP_decodehide();
989                         break;
990                 case svc_showlmp:
991                         SHOWLMP_decodeshow();
992                         break;
993         // LordHavoc: extra worldspawn fields (fog, sky, farclip)
994                 case svc_skybox:
995                         R_SetSkyBox(MSG_ReadString());
996                         break;
997                 case svc_farclip:
998                         r_farclip.value = MSG_ReadCoord();
999                         break;
1000                 case svc_fog:
1001                         if (MSG_ReadByte())
1002                         {
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);
1007                         }
1008                         else
1009                                 fog_density = 0.0f;
1010                         break;
1011                 }
1012         }
1013 }
1014