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