]> icculus.org git repositories - divverent/darkplaces.git/blob - cl_parse.c
added a newline to the end
[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         R_SetSkyBox(""); // 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.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
835
836         VectorCopy (ent->state_baseline.origin, ent->render.origin);
837         VectorCopy (ent->state_baseline.angles, ent->render.angles);    
838 }
839
840 /*
841 ===================
842 CL_ParseStaticSound
843 ===================
844 */
845 void CL_ParseStaticSound (int large)
846 {
847         vec3_t          org;
848         int                     sound_num, vol, atten;
849
850         MSG_ReadVector(org);
851         if (large)
852                 sound_num = (unsigned short) MSG_ReadShort ();
853         else
854                 sound_num = MSG_ReadByte ();
855         vol = MSG_ReadByte ();
856         atten = MSG_ReadByte ();
857         
858         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
859 }
860
861 void CL_ParseEffect (void)
862 {
863         vec3_t          org;
864         int                     modelindex, startframe, framecount, framerate;
865
866         MSG_ReadVector(org);
867         modelindex = MSG_ReadByte ();
868         startframe = MSG_ReadByte ();
869         framecount = MSG_ReadByte ();
870         framerate = MSG_ReadByte ();
871
872         CL_Effect(org, modelindex, startframe, framecount, framerate);
873 }
874
875 void CL_ParseEffect2 (void)
876 {
877         vec3_t          org;
878         int                     modelindex, startframe, framecount, framerate;
879
880         MSG_ReadVector(org);
881         modelindex = MSG_ReadShort ();
882         startframe = MSG_ReadShort ();
883         framecount = MSG_ReadByte ();
884         framerate = MSG_ReadByte ();
885
886         CL_Effect(org, modelindex, startframe, framecount, framerate);
887 }
888
889
890 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
891
892 /*
893 =====================
894 CL_ParseServerMessage
895 =====================
896 */
897 void CL_ParseServerMessage (void)
898 {
899         int                     cmd;
900         int                     i, entitiesupdated;
901         byte            cmdlog[32];
902         char            *cmdlogname[32], *temp;
903         int                     cmdindex, cmdcount = 0;
904         
905 //
906 // if recording demos, copy the message out
907 //
908         if (cl_shownet.value == 1)
909                 Con_Printf ("%i ",net_message.cursize);
910         else if (cl_shownet.value == 2)
911                 Con_Printf ("------------------\n");
912         
913         cl.onground = false;    // unless the server says otherwise     
914 //
915 // parse the message
916 //
917         MSG_BeginReading ();
918
919         entitiesupdated = false;
920         CL_EntityUpdateSetup();
921         
922         while (1)
923         {
924                 if (msg_badread)
925                         Host_Error ("CL_ParseServerMessage: Bad server message");
926
927                 cmd = MSG_ReadByte ();
928
929                 if (cmd == -1)
930                 {
931                         SHOWNET("END OF MESSAGE");
932                         break;          // end of message
933                 }
934
935                 cmdindex = cmdcount & 31;
936                 cmdcount++;
937                 cmdlog[cmdindex] = cmd;
938
939                 // if the high bit of the command byte is set, it is a fast update
940                 if (cmd & 128)
941                 {
942                         // 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)
943                         temp = "entity";
944                         cmdlogname[cmdindex] = temp;
945                         SHOWNET("fast update");
946                         CL_ParseUpdate (cmd&127);
947                         continue;
948                 }
949
950                 SHOWNET(svc_strings[cmd]);
951                 cmdlogname[cmdindex] = svc_strings[cmd];
952                 if (!cmdlogname[cmdindex])
953                 {
954                         // 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)
955                         temp = "<unknown>";
956                         cmdlogname[cmdindex] = temp;
957                 }
958         
959                 // other commands
960                 switch (cmd)
961                 {
962                 default:
963                         {
964                                 char description[32*64], temp[64];
965                                 int count;
966                                 strcpy(description, "packet dump: ");
967                                 i = cmdcount - 32;
968                                 if (i < 0)
969                                         i = 0;
970                                 count = cmdcount - i;
971                                 i &= 31;
972                                 while(count > 0)
973                                 {
974                                         sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
975                                         strcat(description, temp);
976                                         count--;
977                                         i++;
978                                         i &= 31;
979                                 }
980                                 description[strlen(description)-1] = '\n'; // replace the last space with a newline
981                                 Con_Printf(description);
982                                 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
983                         }
984                         break;
985                         
986                 case svc_nop:
987 //                      Con_Printf ("svc_nop\n");
988                         break;
989                         
990                 case svc_time:
991                         // handle old protocols which do not have entity update ranges
992                         entitiesupdated = true;
993                         cl.mtime[1] = cl.mtime[0];
994                         cl.mtime[0] = MSG_ReadFloat ();                 
995                         break;
996                         
997                 case svc_clientdata:
998                         i = MSG_ReadShort ();
999                         CL_ParseClientdata (i);
1000                         break;
1001                 
1002                 case svc_version:
1003                         i = MSG_ReadLong ();
1004                         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
1005                                 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
1006                         Nehahrademcompatibility = false;
1007                         if (i == 250)
1008                                 Nehahrademcompatibility = true;
1009                         if (cls.demoplayback && demo_nehahra.value)
1010                                 Nehahrademcompatibility = true;
1011                         dpprotocol = i == DPPROTOCOL_VERSION;
1012                         break;
1013                         
1014                 case svc_disconnect:
1015                         Host_EndGame ("Server disconnected\n");
1016
1017                 case svc_print:
1018                         Con_Printf ("%s", MSG_ReadString ());
1019                         break;
1020                         
1021                 case svc_centerprint:
1022                         SCR_CenterPrint (MSG_ReadString ());
1023                         break;
1024                         
1025                 case svc_stufftext:
1026                         Cbuf_AddText (MSG_ReadString ());
1027                         break;
1028                         
1029                 case svc_damage:
1030                         V_ParseDamage ();
1031                         break;
1032                         
1033                 case svc_serverinfo:
1034                         CL_ParseServerInfo ();
1035                         vid.recalc_refdef = true;       // leave intermission full screen
1036                         break;
1037                         
1038                 case svc_setangle:
1039                         for (i=0 ; i<3 ; i++)
1040                                 cl.viewangles[i] = MSG_ReadAngle ();
1041                         break;
1042                         
1043                 case svc_setview:
1044                         cl.viewentity = MSG_ReadShort ();
1045                         break;
1046                                         
1047                 case svc_lightstyle:
1048                         i = MSG_ReadByte ();
1049                         if (i >= MAX_LIGHTSTYLES)
1050                                 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1051                         strncpy (cl_lightstyle[i].map,  MSG_ReadString(), MAX_STYLESTRING - 1);
1052                         cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1053                         cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1054                         break;
1055                         
1056                 case svc_sound:
1057                         CL_ParseStartSoundPacket(false);
1058                         break;
1059
1060                 case svc_sound2:
1061                         CL_ParseStartSoundPacket(true);
1062                         break;
1063
1064                 case svc_stopsound:
1065                         i = MSG_ReadShort();
1066                         S_StopSound(i>>3, i&7);
1067                         break;
1068                 
1069                 case svc_updatename:
1070                         i = MSG_ReadByte ();
1071                         if (i >= cl.maxclients)
1072                                 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1073                         strcpy (cl.scores[i].name, MSG_ReadString ());
1074                         break;
1075                         
1076                 case svc_updatefrags:
1077                         i = MSG_ReadByte ();
1078                         if (i >= cl.maxclients)
1079                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1080                         cl.scores[i].frags = MSG_ReadShort ();
1081                         break;                  
1082
1083                 case svc_updatecolors:
1084                         i = MSG_ReadByte ();
1085                         if (i >= cl.maxclients)
1086                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1087                         cl.scores[i].colors = MSG_ReadByte ();
1088                         break;
1089                         
1090                 case svc_particle:
1091                         R_ParseParticleEffect ();
1092                         break;
1093
1094                 case svc_effect:
1095                         CL_ParseEffect ();
1096                         break;
1097
1098                 case svc_effect2:
1099                         CL_ParseEffect2 ();
1100                         break;
1101
1102                 case svc_spawnbaseline:
1103                         i = MSG_ReadShort ();
1104                         // must use CL_EntityNum() to force cl.num_entities up
1105                         CL_ParseBaseline (CL_EntityNum(i), false);
1106                         break;
1107                 case svc_spawnbaseline2:
1108                         i = MSG_ReadShort ();
1109                         // must use CL_EntityNum() to force cl.num_entities up
1110                         CL_ParseBaseline (CL_EntityNum(i), true);
1111                         break;
1112                 case svc_spawnstatic:
1113                         CL_ParseStatic (false);
1114                         break;
1115                 case svc_spawnstatic2:
1116                         CL_ParseStatic (true);
1117                         break;
1118                 case svc_temp_entity:
1119                         CL_ParseTEnt ();
1120                         break;
1121
1122                 case svc_setpause:
1123                         cl.paused = MSG_ReadByte ();
1124                         if (cl.paused)
1125                                 CDAudio_Pause ();
1126                         else
1127                                 CDAudio_Resume ();
1128                         break;
1129                         
1130                 case svc_signonnum:
1131                         i = MSG_ReadByte ();
1132                         if (i <= cls.signon)
1133                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
1134                         cls.signon = i;
1135                         CL_SignonReply ();
1136                         break;
1137
1138                 case svc_killedmonster:
1139                         cl.stats[STAT_MONSTERS]++;
1140                         break;
1141
1142                 case svc_foundsecret:
1143                         cl.stats[STAT_SECRETS]++;
1144                         break;
1145
1146                 case svc_updatestat:
1147                         i = MSG_ReadByte ();
1148                         if (i < 0 || i >= MAX_CL_STATS)
1149                                 Host_Error ("svc_updatestat: %i is invalid", i);
1150                         cl.stats[i] = MSG_ReadLong ();
1151                         break;
1152                         
1153                 case svc_spawnstaticsound:
1154                         CL_ParseStaticSound (false);
1155                         break;
1156
1157                 case svc_spawnstaticsound2:
1158                         CL_ParseStaticSound (true);
1159                         break;
1160
1161                 case svc_cdtrack:
1162                         cl.cdtrack = MSG_ReadByte ();
1163                         cl.looptrack = MSG_ReadByte ();
1164                         if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1165                                 CDAudio_Play ((byte)cls.forcetrack, true);
1166                         else
1167                                 CDAudio_Play ((byte)cl.cdtrack, true);
1168                         break;
1169
1170                 case svc_intermission:
1171                         cl.intermission = 1;
1172                         cl.completed_time = cl.time;
1173                         vid.recalc_refdef = true;       // go to full screen
1174                         break;
1175
1176                 case svc_finale:
1177                         cl.intermission = 2;
1178                         cl.completed_time = cl.time;
1179                         vid.recalc_refdef = true;       // go to full screen
1180                         SCR_CenterPrint (MSG_ReadString ());                    
1181                         break;
1182
1183                 case svc_cutscene:
1184                         cl.intermission = 3;
1185                         cl.completed_time = cl.time;
1186                         vid.recalc_refdef = true;       // go to full screen
1187                         SCR_CenterPrint (MSG_ReadString ());                    
1188                         break;
1189
1190                 case svc_sellscreen:
1191                         Cmd_ExecuteString ("help", src_command);
1192                         break;
1193                 case svc_hidelmp:
1194                         SHOWLMP_decodehide();
1195                         break;
1196                 case svc_showlmp:
1197                         SHOWLMP_decodeshow();
1198                         break;
1199                 }
1200         }
1201
1202         if (entitiesupdated)
1203                 CL_EntityUpdateEnd();
1204 }