]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - cl_parse.c
added a new hack to make MSVC work which will definitely not break any other compilers
[xonotic/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[128] =
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] density*4096 [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 != DPPROTOCOL_VERSION && i != 250)
335         {
336                 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, 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                 if (strlen(str) >= MAX_QPATH)
388                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
389                 strcpy (model_precache[nummodels], str);
390                 Mod_TouchModel (str);
391         }
392
393 // precache sounds
394         memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
395         for (numsounds=1 ; ; numsounds++)
396         {
397                 str = MSG_ReadString ();
398                 if (!str[0])
399                         break;
400                 if (numsounds==MAX_SOUNDS)
401                 {
402                         Con_Printf ("Server sent too many sound precaches\n");
403                         return;
404                 }
405                 if (strlen(str) >= MAX_QPATH)
406                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
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 void CL_ParseUpdate (int bits)
457 {
458         int                     i, modnum, num, alpha, scale, glowsize, glowcolor, colormod;
459         model_t         *model;
460         qboolean        forcelink;
461         entity_t        *ent;
462         entity_state_t *baseline;
463
464         if (cls.signon == SIGNONS - 1)
465         {       // first update is the final signon stage
466                 cls.signon = SIGNONS;
467                 CL_SignonReply ();
468         }
469
470         if (bits & U_MOREBITS)
471                 bits |= (MSG_ReadByte()<<8);
472         if (bits & U_EXTEND1 && !Nehahrademcompatibility)
473         {
474                 bits |= MSG_ReadByte() << 16;
475                 if (bits & U_EXTEND2)
476                         bits |= MSG_ReadByte() << 24;
477         }
478
479         if (bits & U_LONGENTITY)        
480                 num = MSG_ReadShort ();
481         else
482                 num = MSG_ReadByte ();
483
484         ent = CL_EntityNum (num);
485
486         forcelink = ent->msgtime != cl.mtime[1]; // no previous frame to lerp from
487
488         ent->msgtime = cl.mtime[0];
489         
490         // LordHavoc: new protocol stuff
491         baseline = &ent->baseline;
492         if (bits & U_DELTA)
493                 baseline = &ent->deltabaseline;
494
495         if (forcelink)
496         {
497                 ent->deltabaseline.origin[0] = ent->deltabaseline.origin[1] = ent->deltabaseline.origin[2] = 0;
498                 ent->deltabaseline.angles[0] = ent->deltabaseline.angles[1] = ent->deltabaseline.angles[2] = 0;
499                 ent->deltabaseline.effects = 0;
500                 ent->deltabaseline.modelindex = 0;
501                 ent->deltabaseline.frame = 0;
502                 ent->deltabaseline.colormap = 0;
503                 ent->deltabaseline.skin = 0;
504                 ent->deltabaseline.alpha = 255;
505                 ent->deltabaseline.scale = 16;
506                 ent->deltabaseline.glowsize = 0;
507                 ent->deltabaseline.glowcolor = 254;
508                 ent->deltabaseline.colormod = 255;
509         }
510
511         modnum = bits & U_MODEL ? MSG_ReadByte() : baseline->modelindex;
512         if (modnum >= MAX_MODELS)
513                 Host_Error ("CL_ParseModel: bad modnum");
514         ent->deltabaseline.modelindex = modnum;
515                 
516         model = cl.model_precache[modnum];
517         if (model != ent->model)
518         {
519                 ent->model = model;
520         // automatic animation (torches, etc) can be either all together
521         // or randomized
522                 if (model)
523                         ent->syncbase = model->synctype == ST_RAND ? (float)(rand()&0x7fff) / 0x7fff : 0.0;
524                 else
525                         forcelink = true;       // hack to make null model players work
526         }
527
528         ent->frame = ((bits & U_FRAME) ? MSG_ReadByte() : (baseline->frame & 0xFF));
529
530         i = bits & U_COLORMAP ? MSG_ReadByte() : baseline->colormap;
531         ent->deltabaseline.colormap = i;
532         if (!i)
533                 ent->colormap = -1; // no special coloring
534         else
535         {
536                 if (i > cl.maxclients)
537                         Host_Error ("i >= cl.maxclients");
538                 ent->colormap = cl.scores[i-1].colors; // color it
539         }
540
541         ent->deltabaseline.skin = ent->skinnum = bits & U_SKIN ? MSG_ReadByte() : baseline->skin;
542
543         ent->effects = ((bits & U_EFFECTS) ? MSG_ReadByte() : (baseline->effects & 0xFF));
544
545 // shift the known values for interpolation
546         VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
547         VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
548         VectorCopy (baseline->origin, ent->msg_origins[0]);
549         VectorCopy (baseline->angles, ent->msg_angles[0]);
550
551         if (bits & U_ORIGIN1) ent->msg_origins[0][0] = MSG_ReadCoord ();
552         if (bits & U_ANGLE1) ent->msg_angles[0][0] = MSG_ReadAngle();
553         if (bits & U_ORIGIN2) ent->msg_origins[0][1] = MSG_ReadCoord ();
554         if (bits & U_ANGLE2) ent->msg_angles[0][1] = MSG_ReadAngle();
555         if (bits & U_ORIGIN3) ent->msg_origins[0][2] = MSG_ReadCoord ();
556         if (bits & U_ANGLE3) ent->msg_angles[0][2] = MSG_ReadAngle();
557
558         VectorCopy(ent->msg_origins[0], ent->deltabaseline.origin);
559         VectorCopy(ent->msg_angles[0], ent->deltabaseline.angles);
560
561         alpha = bits & U_ALPHA ? MSG_ReadByte() : baseline->alpha;
562         scale = bits & U_SCALE ? MSG_ReadByte() : baseline->scale;
563         ent->effects |= ((bits & U_EFFECTS2) ? (MSG_ReadByte() << 8) : (baseline->effects & 0xFF00));
564         glowsize = bits & U_GLOWSIZE ? MSG_ReadByte() : baseline->glowsize;
565         glowcolor = bits & U_GLOWCOLOR ? MSG_ReadByte() : baseline->glowcolor;
566         colormod = bits & U_COLORMOD ? MSG_ReadByte() : baseline->colormod;
567         ent->frame |= ((bits & U_FRAME2) ? (MSG_ReadByte() << 8) : (baseline->frame & 0xFF00));
568         ent->deltabaseline.alpha = alpha;
569         ent->deltabaseline.scale = scale;
570         ent->deltabaseline.effects = ent->effects;
571         ent->deltabaseline.glowsize = glowsize;
572         ent->deltabaseline.glowcolor = glowcolor;
573         ent->deltabaseline.colormod = colormod;
574         ent->deltabaseline.frame = ent->frame;
575         ent->alpha = (float) alpha * (1.0 / 255.0);
576         ent->scale = (float) scale * (1.0 / 16.0);
577         ent->glowsize = glowsize * 4.0;
578         ent->glowcolor = glowcolor;
579         ent->colormod[0] = (float) ((colormod >> 5) & 7) * (1.0 / 7.0);
580         ent->colormod[1] = (float) ((colormod >> 2) & 7) * (1.0 / 7.0);
581         ent->colormod[2] = (float) (colormod & 3) * (1.0 / 3.0);
582         if (bits & U_EXTEND1 && Nehahrademcompatibility) // LordHavoc: to allow playback of the early Nehahra movie segments
583         {
584                 i = MSG_ReadFloat();
585                 ent->alpha = MSG_ReadFloat();
586                 if (i == 2 && MSG_ReadFloat() != 0.0)
587                         ent->effects |= EF_FULLBRIGHT;
588                 if (ent->alpha == 0)
589                         ent->alpha = 1;
590         }
591
592         //if ( bits & U_NOLERP )
593         //      ent->forcelink = true;
594         //if (bits & U_STEP) // FIXME: implement clientside interpolation of monsters
595
596         if ( forcelink )
597         {       // didn't have an update last message
598                 VectorCopy (ent->msg_origins[0], ent->msg_origins[1]);
599                 VectorCopy (ent->msg_origins[0], ent->origin);
600                 VectorCopy (ent->msg_angles[0], ent->msg_angles[1]);
601                 VectorCopy (ent->msg_angles[0], ent->angles);
602                 ent->forcelink = true;
603         }
604 }
605
606 /*
607 ==================
608 CL_ParseBaseline
609 ==================
610 */
611 void CL_ParseBaseline (entity_t *ent)
612 {
613         int                     i;
614         
615         ent->baseline.modelindex = MSG_ReadByte ();
616         ent->baseline.frame = MSG_ReadByte ();
617         ent->baseline.colormap = MSG_ReadByte();
618         ent->baseline.skin = MSG_ReadByte();
619         for (i=0 ; i<3 ; i++)
620         {
621                 ent->baseline.origin[i] = MSG_ReadCoord ();
622                 ent->baseline.angles[i] = MSG_ReadAngle ();
623         }
624         ent->baseline.alpha = 255;
625         ent->baseline.scale = 16;
626         ent->baseline.glowsize = 0;
627         ent->baseline.glowcolor = 254;
628         ent->baseline.colormod = 255;
629 }
630
631
632 /*
633 ==================
634 CL_ParseClientdata
635
636 Server information pertaining to this client only
637 ==================
638 */
639 void CL_ParseClientdata (int bits)
640 {
641         int             i, j;
642         
643         if (bits & SU_VIEWHEIGHT)
644                 cl.viewheight = MSG_ReadChar ();
645         else
646                 cl.viewheight = DEFAULT_VIEWHEIGHT;
647
648         if (bits & SU_IDEALPITCH)
649                 cl.idealpitch = MSG_ReadChar ();
650         else
651                 cl.idealpitch = 0;
652         
653         VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
654         for (i=0 ; i<3 ; i++)
655         {
656                 if (bits & (SU_PUNCH1<<i) )
657                         cl.punchangle[i] = MSG_ReadChar();
658                 else
659                         cl.punchangle[i] = 0;
660                 if (bits & (SU_VELOCITY1<<i) )
661                         cl.mvelocity[0][i] = MSG_ReadChar()*16;
662                 else
663                         cl.mvelocity[0][i] = 0;
664         }
665
666         i = MSG_ReadLong ();
667         if (cl.items != i)
668         {       // set flash times
669                 for (j=0 ; j<32 ; j++)
670                         if ( (i & (1<<j)) && !(cl.items & (1<<j)))
671                                 cl.item_gettime[j] = cl.time;
672                 cl.items = i;
673         }
674                 
675         cl.onground = (bits & SU_ONGROUND) != 0;
676         cl.inwater = (bits & SU_INWATER) != 0;
677
678         cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
679         cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
680         cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
681         cl.stats[STAT_HEALTH] = MSG_ReadShort();
682         cl.stats[STAT_AMMO] = MSG_ReadByte();
683
684         cl.stats[STAT_SHELLS] = MSG_ReadByte();
685         cl.stats[STAT_NAILS] = MSG_ReadByte();
686         cl.stats[STAT_ROCKETS] = MSG_ReadByte();
687         cl.stats[STAT_CELLS] = MSG_ReadByte();
688
689         i = MSG_ReadByte ();
690
691         if (standard_quake)
692                 cl.stats[STAT_ACTIVEWEAPON] = i;
693         else
694                 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
695 }
696
697 /*
698 =====================
699 CL_ParseStatic
700 =====================
701 */
702 void CL_ParseStatic (void)
703 {
704         entity_t *ent;
705         int             i;
706                 
707         i = cl.num_statics;
708         if (i >= MAX_STATIC_ENTITIES)
709                 Host_Error ("Too many static entities");
710         ent = &cl_static_entities[i];
711         cl.num_statics++;
712         CL_ParseBaseline (ent);
713
714 // copy it to the current state
715         ent->model = cl.model_precache[ent->baseline.modelindex];
716         ent->frame = ent->baseline.frame;
717         ent->colormap = -1; // no special coloring
718         ent->skinnum = ent->baseline.skin;
719         ent->effects = ent->baseline.effects;
720         ent->alpha = 1;
721         ent->scale = 1;
722         ent->alpha = 1;
723         ent->glowsize = 0;
724         ent->glowcolor = 254;
725         ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
726
727         VectorCopy (ent->baseline.origin, ent->origin);
728         VectorCopy (ent->baseline.angles, ent->angles); 
729         R_AddEfrags (ent);
730 }
731
732 /*
733 ===================
734 CL_ParseStaticSound
735 ===================
736 */
737 void CL_ParseStaticSound (void)
738 {
739         vec3_t          org;
740         int                     sound_num, vol, atten;
741         int                     i;
742         
743         for (i=0 ; i<3 ; i++)
744                 org[i] = MSG_ReadCoord ();
745         sound_num = MSG_ReadByte ();
746         vol = MSG_ReadByte ();
747         atten = MSG_ReadByte ();
748         
749         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
750 }
751
752
753 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
754
755 extern void SHOWLMP_decodehide();
756 extern void SHOWLMP_decodeshow();
757 extern void R_SetSkyBox(char* sky);
758
759 /*
760 =====================
761 CL_ParseServerMessage
762 =====================
763 */
764 void CL_ParseServerMessage (void)
765 {
766         int                     cmd;
767         int                     i;
768         byte            cmdlog[32];
769         char            *cmdlogname[32], *temp;
770         int                     cmdindex, cmdcount = 0;
771         
772 //
773 // if recording demos, copy the message out
774 //
775         if (cl_shownet.value == 1)
776                 Con_Printf ("%i ",net_message.cursize);
777         else if (cl_shownet.value == 2)
778                 Con_Printf ("------------------\n");
779         
780         cl.onground = false;    // unless the server says otherwise     
781 //
782 // parse the message
783 //
784         MSG_BeginReading ();
785         
786         while (1)
787         {
788                 if (msg_badread)
789                         Host_Error ("CL_ParseServerMessage: Bad server message");
790
791                 cmd = MSG_ReadByte ();
792
793                 if (cmd == -1)
794                 {
795                         SHOWNET("END OF MESSAGE");
796                         return;         // end of message
797                 }
798
799                 cmdindex = cmdcount & 31;
800                 cmdcount++;
801                 cmdlog[cmdindex] = cmd;
802
803                 // if the high bit of the command byte is set, it is a fast update
804                 if (cmd & 128)
805                 {
806                         // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
807                         temp = "svc_entity";
808                         cmdlogname[cmdindex] = temp;
809                         SHOWNET("fast update");
810                         CL_ParseUpdate (cmd&127);
811                         continue;
812                 }
813
814                 SHOWNET(svc_strings[cmd]);
815                 cmdlogname[cmdindex] = svc_strings[cmd];
816                 if (!cmdlogname[cmdindex])
817                 {
818                         // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
819                         temp = "<unknown>";
820                         cmdlogname[cmdindex] = temp;
821                 }
822         
823                 // other commands
824                 switch (cmd)
825                 {
826                 default:
827                         {
828                                 char description[32*64], temp[64];
829                                 int count;
830                                 strcpy(description, "packet dump: ");
831                                 i = cmdcount - 32;
832                                 if (i < 0)
833                                         i = 0;
834                                 count = cmdcount - i;
835                                 i &= 31;
836                                 while(count > 0)
837                                 {
838                                         sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
839                                         strcat(description, temp);
840                                         count--;
841                                         i++;
842                                         i &= 31;
843                                 }
844                                 description[strlen(description)-1] = '\n'; // replace the last space with a newline
845                                 Con_Printf(description);
846                                 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
847                         }
848                         break;
849                         
850                 case svc_nop:
851 //                      Con_Printf ("svc_nop\n");
852                         break;
853                         
854                 case svc_time:
855                         cl.mtime[1] = cl.mtime[0];
856                         cl.mtime[0] = MSG_ReadFloat ();                 
857                         break;
858                         
859                 case svc_clientdata:
860                         i = MSG_ReadShort ();
861                         CL_ParseClientdata (i);
862                         break;
863                 
864                 case svc_version:
865                         i = MSG_ReadLong ();
866                         if (i != PROTOCOL_VERSION && i != 250)
867                                 Host_Error ("CL_ParseServerMessage: Server is protocol %i instead of %i\n", i, PROTOCOL_VERSION);
868                         Nehahrademcompatibility = i == 250;
869                         break;
870                         
871                 case svc_disconnect:
872                         Host_EndGame ("Server disconnected\n");
873
874                 case svc_print:
875                         Con_Printf ("%s", MSG_ReadString ());
876                         break;
877                         
878                 case svc_centerprint:
879                         SCR_CenterPrint (MSG_ReadString ());
880                         break;
881                         
882                 case svc_stufftext:
883                         Cbuf_AddText (MSG_ReadString ());
884                         break;
885                         
886                 case svc_damage:
887                         V_ParseDamage ();
888                         break;
889                         
890                 case svc_serverinfo:
891                         CL_ParseServerInfo ();
892                         vid.recalc_refdef = true;       // leave intermission full screen
893                         break;
894                         
895                 case svc_setangle:
896                         for (i=0 ; i<3 ; i++)
897                                 cl.viewangles[i] = MSG_ReadAngle ();
898                         break;
899                         
900                 case svc_setview:
901                         cl.viewentity = MSG_ReadShort ();
902                         break;
903                                         
904                 case svc_lightstyle:
905                         i = MSG_ReadByte ();
906                         if (i >= MAX_LIGHTSTYLES)
907                                 Host_Error ("svc_lightstyle > MAX_LIGHTSTYLES");
908                         strcpy (cl_lightstyle[i].map,  MSG_ReadString());
909                         cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
910                         break;
911                         
912                 case svc_sound:
913                         CL_ParseStartSoundPacket();
914                         break;
915                         
916                 case svc_stopsound:
917                         i = MSG_ReadShort();
918                         S_StopSound(i>>3, i&7);
919                         break;
920                 
921                 case svc_updatename:
922                         i = MSG_ReadByte ();
923                         if (i >= cl.maxclients)
924                                 Host_Error ("CL_ParseServerMessage: svc_updatename > MAX_SCOREBOARD");
925                         strcpy (cl.scores[i].name, MSG_ReadString ());
926                         break;
927                         
928                 case svc_updatefrags:
929                         i = MSG_ReadByte ();
930                         if (i >= cl.maxclients)
931                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags > MAX_SCOREBOARD");
932                         cl.scores[i].frags = MSG_ReadShort ();
933                         break;                  
934
935                 case svc_updatecolors:
936                         i = MSG_ReadByte ();
937                         if (i >= cl.maxclients)
938                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
939                         cl.scores[i].colors = MSG_ReadByte ();
940                         break;
941                         
942                 case svc_particle:
943                         R_ParseParticleEffect ();
944                         break;
945
946                 case svc_spawnbaseline:
947                         i = MSG_ReadShort ();
948                         // must use CL_EntityNum() to force cl.num_entities up
949                         CL_ParseBaseline (CL_EntityNum(i));
950                         break;
951                 case svc_spawnstatic:
952                         CL_ParseStatic ();
953                         break;                  
954                 case svc_temp_entity:
955                         CL_ParseTEnt ();
956                         break;
957
958                 case svc_setpause:
959                         cl.paused = MSG_ReadByte ();
960                         if (cl.paused)
961                                 CDAudio_Pause ();
962                         else
963                                 CDAudio_Resume ();
964                         break;
965                         
966                 case svc_signonnum:
967                         i = MSG_ReadByte ();
968                         if (i <= cls.signon)
969                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
970                         cls.signon = i;
971                         CL_SignonReply ();
972                         break;
973
974                 case svc_killedmonster:
975                         cl.stats[STAT_MONSTERS]++;
976                         break;
977
978                 case svc_foundsecret:
979                         cl.stats[STAT_SECRETS]++;
980                         break;
981
982                 case svc_updatestat:
983                         i = MSG_ReadByte ();
984                         if (i < 0 || i >= MAX_CL_STATS)
985                                 Host_Error ("svc_updatestat: %i is invalid", i);
986                         cl.stats[i] = MSG_ReadLong ();;
987                         break;
988                         
989                 case svc_spawnstaticsound:
990                         CL_ParseStaticSound ();
991                         break;
992
993                 case svc_cdtrack:
994                         cl.cdtrack = MSG_ReadByte ();
995                         cl.looptrack = MSG_ReadByte ();
996                         if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
997                                 CDAudio_Play ((byte)cls.forcetrack, true);
998                         else
999                                 CDAudio_Play ((byte)cl.cdtrack, true);
1000                         break;
1001
1002                 case svc_intermission:
1003                         cl.intermission = 1;
1004                         cl.completed_time = cl.time;
1005                         vid.recalc_refdef = true;       // go to full screen
1006                         break;
1007
1008                 case svc_finale:
1009                         cl.intermission = 2;
1010                         cl.completed_time = cl.time;
1011                         vid.recalc_refdef = true;       // go to full screen
1012                         SCR_CenterPrint (MSG_ReadString ());                    
1013                         break;
1014
1015                 case svc_cutscene:
1016                         cl.intermission = 3;
1017                         cl.completed_time = cl.time;
1018                         vid.recalc_refdef = true;       // go to full screen
1019                         SCR_CenterPrint (MSG_ReadString ());                    
1020                         break;
1021
1022                 case svc_sellscreen:
1023                         Cmd_ExecuteString ("help", src_command);
1024                         break;
1025                 case svc_hidelmp:
1026                         SHOWLMP_decodehide();
1027                         break;
1028                 case svc_showlmp:
1029                         SHOWLMP_decodeshow();
1030                         break;
1031         // LordHavoc: extra worldspawn fields (fog, sky, farclip)
1032                 case svc_skybox:
1033                         R_SetSkyBox(MSG_ReadString());
1034                         break;
1035                 case svc_farclip:
1036                         r_farclip.value = MSG_ReadCoord();
1037                         break;
1038                 case svc_fog:
1039                         if (MSG_ReadByte())
1040                         {
1041                                 fog_density = MSG_ReadShort() * (1.0f / 4096.0f);
1042                                 fog_red = MSG_ReadByte() * (1.0 / 255.0);
1043                                 fog_green = MSG_ReadByte() * (1.0 / 255.0);
1044                                 fog_blue = MSG_ReadByte() * (1.0 / 255.0);
1045                         }
1046                         else
1047                                 fog_density = 0.0f;
1048                         break;
1049                 }
1050         }
1051 }
1052