]> icculus.org git repositories - divverent/darkplaces.git/blob - cl_parse.c
some whitespace changes
[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[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 [short] x [short] y
69         "svc_hidelmp",  // [string] iconlabel
70         "", // 37
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         "", // 50
84         "svc_fog", // 51
85         "svc_effect", // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
86         "svc_effect2", // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
87 };
88
89 //=============================================================================
90
91 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
92 qboolean dpprotocol; // LordHavoc: whether or not the current network stream is the enhanced DarkPlaces protocol
93
94 /*
95 ===============
96 CL_EntityNum
97
98 This error checks and tracks the total number of entities
99 ===============
100 */
101 entity_t        *CL_EntityNum (int num)
102 {
103         /*
104         if (num >= cl.num_entities)
105         {
106                 if (num >= MAX_EDICTS)
107                         Host_Error ("CL_EntityNum: %i is an invalid number",num);
108                 cl.num_entities = num;
109 //              while (cl.num_entities <= num)
110 //              {
111 //                      cl_entities[cl.num_entities].colormap = -1; // no special coloring
112 //                      cl.num_entities++;
113 //              }
114         }
115         */
116         if (num >= MAX_EDICTS)
117                 Host_Error ("CL_EntityNum: %i is an invalid number",num);
118                 
119         return &cl_entities[num];
120 }
121
122
123 /*
124 ==================
125 CL_ParseStartSoundPacket
126 ==================
127 */
128 void CL_ParseStartSoundPacket(int largesoundindex)
129 {
130     vec3_t  pos;
131     int         channel, ent;
132     int         sound_num;
133     int         volume;
134     int         field_mask;
135     float       attenuation;
136         int             i;
137                    
138     field_mask = MSG_ReadByte(); 
139
140     if (field_mask & SND_VOLUME)
141                 volume = MSG_ReadByte ();
142         else
143                 volume = DEFAULT_SOUND_PACKET_VOLUME;
144         
145     if (field_mask & SND_ATTENUATION)
146                 attenuation = MSG_ReadByte () / 64.0;
147         else
148                 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
149         
150         channel = MSG_ReadShort ();
151         if (largesoundindex)
152                 sound_num = (unsigned short) MSG_ReadShort ();
153         else
154                 sound_num = MSG_ReadByte ();
155
156         if (sound_num >= MAX_SOUNDS)
157                 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
158
159         ent = channel >> 3;
160         channel &= 7;
161
162         if (ent > MAX_EDICTS)
163                 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
164         
165         for (i=0 ; i<3 ; i++)
166                 pos[i] = MSG_ReadCoord ();
167  
168     S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
169 }       
170
171 /*
172 ==================
173 CL_KeepaliveMessage
174
175 When the client is taking a long time to load stuff, send keepalive messages
176 so the server doesn't disconnect.
177 ==================
178 */
179 void CL_KeepaliveMessage (void)
180 {
181         float   time;
182         static float lastmsg;
183         int             ret;
184         sizebuf_t       old;
185         byte            olddata[8192];
186         
187         if (sv.active)
188                 return;         // no need if server is local
189         if (cls.demoplayback)
190                 return;
191
192 // read messages from server, should just be nops
193         old = net_message;
194         memcpy (olddata, net_message.data, net_message.cursize);
195         
196         do
197         {
198                 ret = CL_GetMessage ();
199                 switch (ret)
200                 {
201                 default:
202                         Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");               
203                 case 0:
204                         break;  // nothing waiting
205                 case 1:
206                         Host_Error ("CL_KeepaliveMessage: received a message");
207                         break;
208                 case 2:
209                         if (MSG_ReadByte() != svc_nop)
210                                 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
211                         break;
212                 }
213         } while (ret);
214
215         net_message = old;
216         memcpy (net_message.data, olddata, net_message.cursize);
217
218 // check time
219         time = Sys_DoubleTime ();
220         if (time - lastmsg < 5)
221                 return;
222         lastmsg = time;
223
224 // write out a nop
225         Con_Printf ("--> client to server keepalive\n");
226
227         MSG_WriteByte (&cls.message, clc_nop);
228         NET_SendMessage (cls.netcon, &cls.message);
229         SZ_Clear (&cls.message);
230 }
231
232 extern qboolean isworldmodel;
233 extern char skyname[];
234 extern void R_SetSkyBox (char *sky);
235 extern void FOG_clear();
236 extern cvar_t r_farclip;
237
238 void CL_ParseEntityLump(char *entdata)
239 {
240         char *data;
241         char key[128], value[4096];
242         char wadname[128];
243         int i, j, k;
244         FOG_clear(); // LordHavoc: no fog until set
245         skyname[0] = 0; // LordHavoc: no enviroment mapped sky until set
246         r_farclip.value = 6144; // LordHavoc: default farclip distance
247         data = entdata;
248         if (!data)
249                 return;
250         data = COM_Parse(data);
251         if (!data)
252                 return; // valid exit
253         if (com_token[0] != '{')
254                 return; // error
255         while (1)
256         {
257                 data = COM_Parse(data);
258                 if (!data)
259                         return; // error
260                 if (com_token[0] == '}')
261                         return; // since we're just parsing the first ent (worldspawn), exit
262                 strcpy(key, com_token);
263                 while (key[strlen(key)-1] == ' ') // remove trailing spaces
264                         key[strlen(key)-1] = 0;
265                 data = COM_Parse(data);
266                 if (!data)
267                         return; // error
268                 strcpy(value, com_token);
269                 if (!strcmp("sky", key))
270                         R_SetSkyBox(value);
271                 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
272                         R_SetSkyBox(value);
273                 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
274                         R_SetSkyBox(value);
275                 else if (!strcmp("farclip", key))
276                 {
277                         r_farclip.value = atof(value);
278                         if (r_farclip.value < 64)
279                                 r_farclip.value = 64;
280                 }
281                 else if (!strcmp("fog", key))
282                 {
283                         scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
284                         j = 0;
285                 }
286                 else if (!strcmp("fog_density", key))
287                         fog_density = atof(value);
288                 else if (!strcmp("fog_red", key))
289                         fog_red = atof(value);
290                 else if (!strcmp("fog_green", key))
291                         fog_green = atof(value);
292                 else if (!strcmp("fog_blue", key))
293                         fog_blue = atof(value);
294                 else if (!strcmp("wad", key)) // for HalfLife maps
295                 {
296                         if (hlbsp)
297                         {
298                                 j = 0;
299                                 for (i = 0;i < 4096;i++)
300                                         if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
301                                                 break;
302                                 if (value[i])
303                                 {
304                                         for (;i < 4096;i++)
305                                         {
306                                                 // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
307                                                 if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
308                                                         j = i+1;
309                                                 else if (value[i] == ';' || value[i] == 0)
310                                                 {
311                                                         k = value[i];
312                                                         value[i] = 0;
313                                                         strcpy(wadname, "textures/");
314                                                         strcat(wadname, &value[j]);
315                                                         W_LoadTextureWadFile (wadname, false);
316                                                         j = i+1;
317                                                         if (!k)
318                                                                 break;
319                                                 }
320                                         }
321                                 }
322                         }
323                 }
324         }
325 }
326
327 /*
328 ==================
329 CL_ParseServerInfo
330 ==================
331 */
332 extern cvar_t demo_nehahra;
333 void CL_ParseServerInfo (void)
334 {
335         char    *str;
336         int             i;
337         int             nummodels, numsounds;
338         char    model_precache[MAX_MODELS][MAX_QPATH];
339         char    sound_precache[MAX_SOUNDS][MAX_QPATH];
340         
341         Con_DPrintf ("Serverinfo packet received.\n");
342 //
343 // wipe the client_state_t struct
344 //
345         CL_ClearState ();
346
347 // parse protocol version number
348         i = MSG_ReadLong ();
349         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
350         {
351                 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
352                 return;
353         }
354         Nehahrademcompatibility = false;
355         if (i == 250)
356                 Nehahrademcompatibility = true;
357         if (cls.demoplayback && demo_nehahra.value)
358                 Nehahrademcompatibility = true;
359         dpprotocol = i == DPPROTOCOL_VERSION;
360
361 // parse maxclients
362         cl.maxclients = MSG_ReadByte ();
363         if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
364         {
365                 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
366                 return;
367         }
368         cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
369
370 // parse gametype
371         cl.gametype = MSG_ReadByte ();
372
373 // parse signon message
374         str = MSG_ReadString ();
375         strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
376
377 // seperate the printfs so the server message can have a color
378         if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
379         {
380                 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");
381                 Con_Printf ("%c%s\n", 2, str);
382         }
383
384 //
385 // first we go through and touch all of the precache data that still
386 // happens to be in the cache, so precaching something else doesn't
387 // needlessly purge it
388 //
389
390 // precache models
391         memset (cl.model_precache, 0, sizeof(cl.model_precache));
392         for (nummodels=1 ; ; nummodels++)
393         {
394                 str = MSG_ReadString ();
395                 if (!str[0])
396                         break;
397                 if (nummodels==MAX_MODELS)
398                 {
399                         Con_Printf ("Server sent too many model precaches\n");
400                         return;
401                 }
402                 if (strlen(str) >= MAX_QPATH)
403                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
404                 strcpy (model_precache[nummodels], str);
405                 Mod_TouchModel (str);
406         }
407
408 // precache sounds
409         memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
410         for (numsounds=1 ; ; numsounds++)
411         {
412                 str = MSG_ReadString ();
413                 if (!str[0])
414                         break;
415                 if (numsounds==MAX_SOUNDS)
416                 {
417                         Con_Printf ("Server sent too many sound precaches\n");
418                         return;
419                 }
420                 if (strlen(str) >= MAX_QPATH)
421                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
422                 strcpy (sound_precache[numsounds], str);
423                 S_TouchSound (str);
424         }
425
426 //
427 // now we try to load everything else until a cache allocation fails
428 //
429
430         for (i=1 ; i<nummodels ; i++)
431         {
432                 isworldmodel = i == 1; // LordHavoc: first model is the world model
433                 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
434                 if (cl.model_precache[i] == NULL)
435                 {
436                         Con_Printf("Model %s not found\n", model_precache[i]);
437                         return;
438                 }
439                 CL_KeepaliveMessage ();
440         }
441
442         S_BeginPrecaching ();
443         for (i=1 ; i<numsounds ; i++)
444         {
445                 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
446                 CL_KeepaliveMessage ();
447         }
448         S_EndPrecaching ();
449
450
451 // local state
452         cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
453         
454         R_NewMap ();
455
456         Hunk_Check ();          // make sure nothing is hurt
457         
458         noclip_anglehack = false;               // noclip is turned off at start        
459 }
460
461 void CL_ValidateState(entity_state_t *s)
462 {
463         model_t *model;
464
465         if (!s->active)
466                 return;
467
468         if (s->modelindex >= MAX_MODELS)
469                 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
470
471         // colormap is client index + 1
472         if (s->colormap > cl.maxclients)
473                 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
474
475         model = cl.model_precache[s->modelindex];
476         if (model && s->frame >= model->numframes)
477         {
478                 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
479                 s->frame = 0;
480         }
481 }
482
483 /*
484 ==================
485 CL_ParseUpdate
486
487 Parse an entity update message from the server
488 If an entities model or origin changes from frame to frame, it must be
489 relinked.  Other attributes can change without relinking.
490 ==================
491 */
492 byte entkill[MAX_EDICTS];
493 int bitprofile[32], bitprofilecount = 0;
494 void CL_ParseUpdate (int bits)
495 {
496         int i, num, deltadie;
497         entity_t *ent;
498
499         if (cls.signon == SIGNONS - 1)
500         {       // first update is the final signon stage
501                 cls.signon = SIGNONS;
502                 CL_SignonReply ();
503         }
504
505         if (bits & U_MOREBITS)
506                 bits |= (MSG_ReadByte()<<8);
507         if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
508         {
509                 bits |= MSG_ReadByte() << 16;
510                 if (bits & U_EXTEND2)
511                         bits |= MSG_ReadByte() << 24;
512         }
513
514         if (bits & U_LONGENTITY)        
515                 num = (unsigned) MSG_ReadShort ();
516         else
517                 num = (unsigned) MSG_ReadByte ();
518
519         if (num >= MAX_EDICTS)
520                 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
521         if (num < 1)
522                 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
523
524         // mark as visible (no kill)
525         entkill[num] = 0;
526
527         ent = CL_EntityNum (num);
528
529         for (i = 0;i < 32;i++)
530                 if (bits & (1 << i))
531                         bitprofile[i]++;
532         bitprofilecount++;
533
534         ent->state_previous = ent->state_current;
535         deltadie = false;
536         if (bits & U_DELTA)
537         {
538                 if (!ent->state_current.active)
539                         deltadie = true; // was not present in previous frame, leave hidden until next full update
540         }
541         else
542                 ent->state_current = ent->state_baseline;
543
544         ent->state_current.time = cl.mtime[0];
545
546         ent->state_current.flags = 0;
547         ent->state_current.active = true;
548         if (bits & U_MODEL)             ent->state_current.modelindex = (ent->state_current.modelindex & 0xFF00) | MSG_ReadByte();
549         if (bits & U_FRAME)             ent->state_current.frame = (ent->state_current.frame & 0xFF00) | MSG_ReadByte();
550         if (bits & U_COLORMAP)  ent->state_current.colormap = MSG_ReadByte();
551         if (bits & U_SKIN)              ent->state_current.skin = MSG_ReadByte();
552         if (bits & U_EFFECTS)   ent->state_current.effects = (ent->state_current.effects & 0xFF00) | MSG_ReadByte();
553         if (bits & U_ORIGIN1)   ent->state_current.origin[0] = MSG_ReadCoord();
554         if (bits & U_ANGLE1)    ent->state_current.angles[0] = MSG_ReadAngle();
555         if (bits & U_ORIGIN2)   ent->state_current.origin[1] = MSG_ReadCoord();
556         if (bits & U_ANGLE2)    ent->state_current.angles[1] = MSG_ReadAngle();
557         if (bits & U_ORIGIN3)   ent->state_current.origin[2] = MSG_ReadCoord();
558         if (bits & U_ANGLE3)    ent->state_current.angles[2] = MSG_ReadAngle();
559         if (bits & U_STEP)              ent->state_current.flags |= RENDER_STEP;
560         if (bits & U_ALPHA)             ent->state_current.alpha = MSG_ReadByte();
561         if (bits & U_SCALE)             ent->state_current.scale = MSG_ReadByte();
562         if (bits & U_EFFECTS2)  ent->state_current.effects = (ent->state_current.effects & 0x00FF) | (MSG_ReadByte() << 8);
563         if (bits & U_GLOWSIZE)  ent->state_current.glowsize = MSG_ReadByte();
564         if (bits & U_GLOWCOLOR) ent->state_current.glowcolor = MSG_ReadByte();
565         if (bits & U_GLOWTRAIL) ent->state_current.flags |= RENDER_GLOWTRAIL;
566         if (bits & U_COLORMOD)  ent->state_current.colormod = MSG_ReadByte();
567         if (bits & U_FRAME2)    ent->state_current.frame = (ent->state_current.frame & 0x00FF) | (MSG_ReadByte() << 8);
568         if (bits & U_MODEL2)    ent->state_current.modelindex = (ent->state_current.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
569         if (bits & U_VIEWMODEL) ent->state_current.flags |= RENDER_VIEWMODEL;
570         if (bits & U_EXTERIORMODEL)     ent->state_current.flags |= RENDER_EXTERIORMODEL;
571
572         // LordHavoc: to allow playback of the Nehahra movie
573         if (Nehahrademcompatibility && (bits & U_EXTEND1))
574         {
575                 // LordHavoc: evil format
576                 int i = MSG_ReadFloat();
577                 int j = MSG_ReadFloat() * 255.0f;
578                 if (i == 2)
579                 {
580                         if (MSG_ReadFloat())
581                                 ent->state_current.effects |= EF_FULLBRIGHT;
582                 }
583                 if (j < 0)
584                         ent->state_current.alpha = 0;
585                 else if (j == 0 || j >= 255)
586                         ent->state_current.alpha = 255;
587                 else
588                         ent->state_current.alpha = j;
589         }
590
591         if (deltadie)
592         {
593                 // hide the entity
594                 ent->state_current.active = false;
595         }
596         else
597         {
598                 CL_ValidateState(&ent->state_current);
599
600                 /*
601                 if (!ent->state_current.active)
602                 {
603                         if (bits & U_DELTA)
604                         {
605                                 if (bits & U_MODEL)
606                                         Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i %i\n", num, ent->state_previous.modelindex, ent->state_current.modelindex);
607                                 else
608                                         Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i\n", num, ent->state_previous.modelindex);
609                         }
610                         else
611                         {
612                                 if (bits & U_MODEL)
613                                         Con_Printf("CL_ParseUpdate:       NULL model on %i: %i %i\n", num, ent->state_baseline.modelindex, ent->state_current.modelindex);
614                                 else
615                                         Con_Printf("CL_ParseUpdate:       NULL model on %i: %i\n", num, ent->state_baseline.modelindex);
616                         }
617                 }
618                 */
619         }
620 }
621
622 char *bitprofilenames[32] =
623 {
624         "U_MOREBITS",
625         "U_ORIGIN1",
626         "U_ORIGIN2",
627         "U_ORIGIN3",
628         "U_ANGLE2",
629         "U_STEP",
630         "U_FRAME",
631         "U_SIGNAL",
632         "U_ANGLE1",
633         "U_ANGLE3",
634         "U_MODEL",
635         "U_COLORMAP",
636         "U_SKIN",
637         "U_EFFECTS",
638         "U_LONGENTITY",
639         "U_EXTEND1",
640         "U_DELTA",
641         "U_ALPHA",
642         "U_SCALE",
643         "U_EFFECTS2",
644         "U_GLOWSIZE",
645         "U_GLOWCOLOR",
646         "U_COLORMOD",
647         "U_EXTEND2",
648         "U_GLOWTRAIL",
649         "U_VIEWMODEL",
650         "U_FRAME2",
651         "U_MODEL2",
652         "U_EXTERIORMODEL",
653         "U_UNUSED29",
654         "U_UNUSED30",
655         "U_EXTEND3",
656 };
657
658 void CL_BitProfile_f(void)
659 {
660         int i;
661         Con_Printf("bitprofile: %i updates\n");
662         if (bitprofilecount)
663                 for (i = 0;i < 32;i++)
664 //                      if (bitprofile[i])
665                                 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
666         Con_Printf("\n");
667         for (i = 0;i < 32;i++)
668                 bitprofile[i] = 0;
669         bitprofilecount = 0;
670 }
671
672 void CL_EntityUpdateSetup()
673 {
674         memset(entkill, 1, MAX_EDICTS);
675 }
676
677 void CL_EntityUpdateEnd()
678 {
679         int i;
680         for (i = 1;i < MAX_EDICTS;i++)
681                 if (entkill[i])
682                         cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
683 }
684
685 /*
686 ==================
687 CL_ParseBaseline
688 ==================
689 */
690 void CL_ParseBaseline (entity_t *ent, int large)
691 {
692         int i;
693
694         memset(&ent->state_baseline, 0, sizeof(entity_state_t));
695         ent->state_baseline.active = true;
696         if (large)
697         {
698                 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
699                 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
700         }
701         else
702         {
703                 ent->state_baseline.modelindex = MSG_ReadByte ();
704                 ent->state_baseline.frame = MSG_ReadByte ();
705         }
706         ent->state_baseline.colormap = MSG_ReadByte();
707         ent->state_baseline.skin = MSG_ReadByte();
708         for (i = 0;i < 3;i++)
709         {
710                 ent->state_baseline.origin[i] = MSG_ReadCoord ();
711                 ent->state_baseline.angles[i] = MSG_ReadAngle ();
712         }
713         ent->state_baseline.alpha = 255;
714         ent->state_baseline.scale = 16;
715         ent->state_baseline.glowsize = 0;
716         ent->state_baseline.glowcolor = 254;
717         ent->state_baseline.colormod = 255;
718         ent->state_previous = ent->state_current = ent->state_baseline;
719
720         CL_ValidateState(&ent->state_baseline);
721 }
722
723
724 /*
725 ==================
726 CL_ParseClientdata
727
728 Server information pertaining to this client only
729 ==================
730 */
731 void CL_ParseClientdata (int bits)
732 {
733         int i, j;
734
735         bits &= 0xFFFF;
736         if (bits & SU_EXTEND1)
737                 bits |= (MSG_ReadByte() << 16);
738         if (bits & SU_EXTEND2)
739                 bits |= (MSG_ReadByte() << 24);
740
741         if (bits & SU_VIEWHEIGHT)
742                 cl.viewheight = MSG_ReadChar ();
743         else
744                 cl.viewheight = DEFAULT_VIEWHEIGHT;
745
746         if (bits & SU_IDEALPITCH)
747                 cl.idealpitch = MSG_ReadChar ();
748         else
749                 cl.idealpitch = 0;
750         
751         VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
752         for (i=0 ; i<3 ; i++)
753         {
754                 if (bits & (SU_PUNCH1<<i) )
755                 {
756                         if (dpprotocol)
757                                 cl.punchangle[i] = MSG_ReadPreciseAngle();
758                         else
759                                 cl.punchangle[i] = MSG_ReadChar();
760                 }
761                 else
762                         cl.punchangle[i] = 0;
763                 if (bits & (SU_PUNCHVEC1<<i))
764                         cl.punchvector[i] = MSG_ReadFloatCoord();
765                 else
766                         cl.punchvector[i] = 0;
767                 if (bits & (SU_VELOCITY1<<i) )
768                         cl.mvelocity[0][i] = MSG_ReadChar()*16;
769                 else
770                         cl.mvelocity[0][i] = 0;
771         }
772
773         i = MSG_ReadLong ();
774         if (cl.items != i)
775         {       // set flash times
776                 for (j=0 ; j<32 ; j++)
777                         if ( (i & (1<<j)) && !(cl.items & (1<<j)))
778                                 cl.item_gettime[j] = cl.time;
779                 cl.items = i;
780         }
781                 
782         cl.onground = (bits & SU_ONGROUND) != 0;
783         cl.inwater = (bits & SU_INWATER) != 0;
784
785         cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
786         cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
787         cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
788         cl.stats[STAT_HEALTH] = MSG_ReadShort();
789         cl.stats[STAT_AMMO] = MSG_ReadByte();
790
791         cl.stats[STAT_SHELLS] = MSG_ReadByte();
792         cl.stats[STAT_NAILS] = MSG_ReadByte();
793         cl.stats[STAT_ROCKETS] = MSG_ReadByte();
794         cl.stats[STAT_CELLS] = MSG_ReadByte();
795
796         i = MSG_ReadByte ();
797
798         if (standard_quake)
799                 cl.stats[STAT_ACTIVEWEAPON] = i;
800         else
801                 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
802 }
803
804 /*
805 =====================
806 CL_ParseStatic
807 =====================
808 */
809 void CL_ParseStatic (int large)
810 {
811         entity_t *ent;
812                 
813         if (cl.num_statics >= MAX_STATIC_ENTITIES)
814                 Host_Error ("Too many static entities");
815         ent = &cl_static_entities[cl.num_statics++];
816         CL_ParseBaseline (ent, large);
817
818 // copy it to the current state
819         ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
820         ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
821         ent->render.framelerp = 0;
822         ent->render.lerp_starttime = -1;
823         // make torchs play out of sync
824         ent->render.frame1start = ent->render.frame2start = -(rand() & 32767);
825         ent->render.colormap = -1; // no special coloring
826         ent->render.skinnum = ent->state_baseline.skin;
827         ent->render.effects = ent->state_baseline.effects;
828         ent->render.alpha = 1;
829         ent->render.scale = 1;
830         ent->render.alpha = 1;
831         ent->render.glowsize = 0;
832         ent->render.glowcolor = 254;
833         ent->render.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
834
835         VectorCopy (ent->state_baseline.origin, ent->render.origin);
836         VectorCopy (ent->state_baseline.angles, ent->render.angles);    
837 }
838
839 /*
840 ===================
841 CL_ParseStaticSound
842 ===================
843 */
844 void CL_ParseStaticSound (int large)
845 {
846         vec3_t          org;
847         int                     sound_num, vol, atten;
848
849         MSG_ReadVector(org);
850         if (large)
851                 sound_num = (unsigned short) MSG_ReadShort ();
852         else
853                 sound_num = MSG_ReadByte ();
854         vol = MSG_ReadByte ();
855         atten = MSG_ReadByte ();
856         
857         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
858 }
859
860 void CL_ParseEffect (void)
861 {
862         vec3_t          org;
863         int                     modelindex, startframe, framecount, framerate;
864
865         MSG_ReadVector(org);
866         modelindex = MSG_ReadByte ();
867         startframe = MSG_ReadByte ();
868         framecount = MSG_ReadByte ();
869         framerate = MSG_ReadByte ();
870
871         CL_Effect(org, modelindex, startframe, framecount, framerate);
872 }
873
874 void CL_ParseEffect2 (void)
875 {
876         vec3_t          org;
877         int                     modelindex, startframe, framecount, framerate;
878
879         MSG_ReadVector(org);
880         modelindex = MSG_ReadShort ();
881         startframe = MSG_ReadShort ();
882         framecount = MSG_ReadByte ();
883         framerate = MSG_ReadByte ();
884
885         CL_Effect(org, modelindex, startframe, framecount, framerate);
886 }
887
888
889 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
890
891 extern void SHOWLMP_decodehide();
892 extern void SHOWLMP_decodeshow();
893 extern void R_SetSkyBox(char* sky);
894 extern int netshown;
895
896 /*
897 =====================
898 CL_ParseServerMessage
899 =====================
900 */
901 void CL_ParseServerMessage (void)
902 {
903         int                     cmd;
904         int                     i, entitiesupdated;
905         byte            cmdlog[32];
906         char            *cmdlogname[32], *temp;
907         int                     cmdindex, cmdcount = 0;
908         
909 //
910 // if recording demos, copy the message out
911 //
912         if (cl_shownet.value == 1)
913         {
914                 Con_Printf ("%i ",net_message.cursize);
915                 netshown = true;
916         }
917         else if (cl_shownet.value == 2)
918         {
919                 Con_Printf ("------------------\n");
920                 netshown = true;
921         }
922         
923         cl.onground = false;    // unless the server says otherwise     
924 //
925 // parse the message
926 //
927         MSG_BeginReading ();
928
929         entitiesupdated = false;
930         CL_EntityUpdateSetup();
931         
932         while (1)
933         {
934                 if (msg_badread)
935                         Host_Error ("CL_ParseServerMessage: Bad server message");
936
937                 cmd = MSG_ReadByte ();
938
939                 if (cmd == -1)
940                 {
941                         SHOWNET("END OF MESSAGE");
942                         break;          // end of message
943                 }
944
945                 cmdindex = cmdcount & 31;
946                 cmdcount++;
947                 cmdlog[cmdindex] = cmd;
948
949                 // if the high bit of the command byte is set, it is a fast update
950                 if (cmd & 128)
951                 {
952                         // 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)
953                         temp = "entity";
954                         cmdlogname[cmdindex] = temp;
955                         SHOWNET("fast update");
956                         CL_ParseUpdate (cmd&127);
957                         continue;
958                 }
959
960                 SHOWNET(svc_strings[cmd]);
961                 cmdlogname[cmdindex] = svc_strings[cmd];
962                 if (!cmdlogname[cmdindex])
963                 {
964                         // 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)
965                         temp = "<unknown>";
966                         cmdlogname[cmdindex] = temp;
967                 }
968         
969                 // other commands
970                 switch (cmd)
971                 {
972                 default:
973                         {
974                                 char description[32*64], temp[64];
975                                 int count;
976                                 strcpy(description, "packet dump: ");
977                                 i = cmdcount - 32;
978                                 if (i < 0)
979                                         i = 0;
980                                 count = cmdcount - i;
981                                 i &= 31;
982                                 while(count > 0)
983                                 {
984                                         sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
985                                         strcat(description, temp);
986                                         count--;
987                                         i++;
988                                         i &= 31;
989                                 }
990                                 description[strlen(description)-1] = '\n'; // replace the last space with a newline
991                                 Con_Printf(description);
992                                 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
993                         }
994                         break;
995                         
996                 case svc_nop:
997 //                      Con_Printf ("svc_nop\n");
998                         break;
999                         
1000                 case svc_time:
1001                         // handle old protocols which do not have entity update ranges
1002                         entitiesupdated = true;
1003                         cl.mtime[1] = cl.mtime[0];
1004                         cl.mtime[0] = MSG_ReadFloat ();                 
1005                         break;
1006                         
1007                 case svc_clientdata:
1008                         i = MSG_ReadShort ();
1009                         CL_ParseClientdata (i);
1010                         break;
1011                 
1012                 case svc_version:
1013                         i = MSG_ReadLong ();
1014                         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
1015                                 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
1016                         Nehahrademcompatibility = false;
1017                         if (i == 250)
1018                                 Nehahrademcompatibility = true;
1019                         if (cls.demoplayback && demo_nehahra.value)
1020                                 Nehahrademcompatibility = true;
1021                         dpprotocol = i == DPPROTOCOL_VERSION;
1022                         break;
1023                         
1024                 case svc_disconnect:
1025                         Host_EndGame ("Server disconnected\n");
1026
1027                 case svc_print:
1028                         Con_Printf ("%s", MSG_ReadString ());
1029                         break;
1030                         
1031                 case svc_centerprint:
1032                         SCR_CenterPrint (MSG_ReadString ());
1033                         break;
1034                         
1035                 case svc_stufftext:
1036                         Cbuf_AddText (MSG_ReadString ());
1037                         break;
1038                         
1039                 case svc_damage:
1040                         V_ParseDamage ();
1041                         break;
1042                         
1043                 case svc_serverinfo:
1044                         CL_ParseServerInfo ();
1045                         vid.recalc_refdef = true;       // leave intermission full screen
1046                         break;
1047                         
1048                 case svc_setangle:
1049                         for (i=0 ; i<3 ; i++)
1050                                 cl.viewangles[i] = MSG_ReadAngle ();
1051                         break;
1052                         
1053                 case svc_setview:
1054                         cl.viewentity = MSG_ReadShort ();
1055                         break;
1056                                         
1057                 case svc_lightstyle:
1058                         i = MSG_ReadByte ();
1059                         if (i >= MAX_LIGHTSTYLES)
1060                                 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1061                         strncpy (cl_lightstyle[i].map,  MSG_ReadString(), MAX_STYLESTRING - 1);
1062                         cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1063                         cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1064                         break;
1065                         
1066                 case svc_sound:
1067                         CL_ParseStartSoundPacket(false);
1068                         break;
1069
1070                 case svc_sound2:
1071                         CL_ParseStartSoundPacket(true);
1072                         break;
1073
1074                 case svc_stopsound:
1075                         i = MSG_ReadShort();
1076                         S_StopSound(i>>3, i&7);
1077                         break;
1078                 
1079                 case svc_updatename:
1080                         i = MSG_ReadByte ();
1081                         if (i >= cl.maxclients)
1082                                 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1083                         strcpy (cl.scores[i].name, MSG_ReadString ());
1084                         break;
1085                         
1086                 case svc_updatefrags:
1087                         i = MSG_ReadByte ();
1088                         if (i >= cl.maxclients)
1089                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1090                         cl.scores[i].frags = MSG_ReadShort ();
1091                         break;                  
1092
1093                 case svc_updatecolors:
1094                         i = MSG_ReadByte ();
1095                         if (i >= cl.maxclients)
1096                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1097                         cl.scores[i].colors = MSG_ReadByte ();
1098                         break;
1099                         
1100                 case svc_particle:
1101                         R_ParseParticleEffect ();
1102                         break;
1103
1104                 case svc_effect:
1105                         CL_ParseEffect ();
1106                         break;
1107
1108                 case svc_effect2:
1109                         CL_ParseEffect2 ();
1110                         break;
1111
1112                 case svc_spawnbaseline:
1113                         i = MSG_ReadShort ();
1114                         // must use CL_EntityNum() to force cl.num_entities up
1115                         CL_ParseBaseline (CL_EntityNum(i), false);
1116                         break;
1117                 case svc_spawnbaseline2:
1118                         i = MSG_ReadShort ();
1119                         // must use CL_EntityNum() to force cl.num_entities up
1120                         CL_ParseBaseline (CL_EntityNum(i), true);
1121                         break;
1122                 case svc_spawnstatic:
1123                         CL_ParseStatic (false);
1124                         break;
1125                 case svc_spawnstatic2:
1126                         CL_ParseStatic (true);
1127                         break;
1128                 case svc_temp_entity:
1129                         CL_ParseTEnt ();
1130                         break;
1131
1132                 case svc_setpause:
1133                         cl.paused = MSG_ReadByte ();
1134                         if (cl.paused)
1135                                 CDAudio_Pause ();
1136                         else
1137                                 CDAudio_Resume ();
1138                         break;
1139                         
1140                 case svc_signonnum:
1141                         i = MSG_ReadByte ();
1142                         if (i <= cls.signon)
1143                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
1144                         cls.signon = i;
1145                         CL_SignonReply ();
1146                         break;
1147
1148                 case svc_killedmonster:
1149                         cl.stats[STAT_MONSTERS]++;
1150                         break;
1151
1152                 case svc_foundsecret:
1153                         cl.stats[STAT_SECRETS]++;
1154                         break;
1155
1156                 case svc_updatestat:
1157                         i = MSG_ReadByte ();
1158                         if (i < 0 || i >= MAX_CL_STATS)
1159                                 Host_Error ("svc_updatestat: %i is invalid", i);
1160                         cl.stats[i] = MSG_ReadLong ();
1161                         break;
1162                         
1163                 case svc_spawnstaticsound:
1164                         CL_ParseStaticSound (false);
1165                         break;
1166
1167                 case svc_spawnstaticsound2:
1168                         CL_ParseStaticSound (true);
1169                         break;
1170
1171                 case svc_cdtrack:
1172                         cl.cdtrack = MSG_ReadByte ();
1173                         cl.looptrack = MSG_ReadByte ();
1174                         if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1175                                 CDAudio_Play ((byte)cls.forcetrack, true);
1176                         else
1177                                 CDAudio_Play ((byte)cl.cdtrack, true);
1178                         break;
1179
1180                 case svc_intermission:
1181                         cl.intermission = 1;
1182                         cl.completed_time = cl.time;
1183                         vid.recalc_refdef = true;       // go to full screen
1184                         break;
1185
1186                 case svc_finale:
1187                         cl.intermission = 2;
1188                         cl.completed_time = cl.time;
1189                         vid.recalc_refdef = true;       // go to full screen
1190                         SCR_CenterPrint (MSG_ReadString ());                    
1191                         break;
1192
1193                 case svc_cutscene:
1194                         cl.intermission = 3;
1195                         cl.completed_time = cl.time;
1196                         vid.recalc_refdef = true;       // go to full screen
1197                         SCR_CenterPrint (MSG_ReadString ());                    
1198                         break;
1199
1200                 case svc_sellscreen:
1201                         Cmd_ExecuteString ("help", src_command);
1202                         break;
1203                 case svc_hidelmp:
1204                         SHOWLMP_decodehide();
1205                         break;
1206                 case svc_showlmp:
1207                         SHOWLMP_decodeshow();
1208                         break;
1209                 }
1210         }
1211
1212         if (entitiesupdated)
1213                 CL_EntityUpdateEnd();
1214 }