]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - cl_parse.c
made directional static lighting work, then disabled it because it is not practical...
[xonotic/darkplaces.git] / cl_parse.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // cl_parse.c  -- parse a message received from the server
21
22 #include "quakedef.h"
23
24 char *svc_strings[128] =
25 {
26         "svc_bad",
27         "svc_nop",
28         "svc_disconnect",
29         "svc_updatestat",
30         "svc_version",          // [long] server version
31         "svc_setview",          // [short] entity number
32         "svc_sound",                    // <see code>
33         "svc_time",                     // [float] server time
34         "svc_print",                    // [string] null terminated string
35         "svc_stufftext",                // [string] stuffed into client's console buffer
36                                                 // the string should be \n terminated
37         "svc_setangle",         // [vec3] set the view angle to this absolute value
38
39         "svc_serverinfo",               // [long] version
40                                                 // [string] signon string
41                                                 // [string]..[0]model cache [string]...[0]sounds cache
42                                                 // [string]..[0]item cache
43         "svc_lightstyle",               // [byte] [string]
44         "svc_updatename",               // [byte] [string]
45         "svc_updatefrags",      // [byte] [short]
46         "svc_clientdata",               // <shortbits + data>
47         "svc_stopsound",                // <see code>
48         "svc_updatecolors",     // [byte] [byte]
49         "svc_particle",         // [vec3] <variable>
50         "svc_damage",                   // [byte] impact [byte] blood [vec3] from
51         
52         "svc_spawnstatic",
53         "OBSOLETE svc_spawnbinary",
54         "svc_spawnbaseline",
55         
56         "svc_temp_entity",              // <variable>
57         "svc_setpause",
58         "svc_signonnum",
59         "svc_centerprint",
60         "svc_killedmonster",
61         "svc_foundsecret",
62         "svc_spawnstaticsound",
63         "svc_intermission",
64         "svc_finale",                   // [string] music [string] text
65         "svc_cdtrack",                  // [byte] track [byte] looptrack
66         "svc_sellscreen",
67         "svc_cutscene",
68         "svc_showlmp",  // [string] iconlabel [string] lmpfile [short] x [short] y
69         "svc_hidelmp",  // [string] iconlabel
70         "svc_skybox", // [string] skyname
71         "", // 38
72         "", // 39
73         "", // 40
74         "", // 41
75         "", // 42
76         "", // 43
77         "", // 44
78         "", // 45
79         "", // 46
80         "", // 47
81         "", // 48
82         "", // 49
83         "", // 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 = {0, "demo_nehahra", "0"};
92
93 void CL_Parse_Init(void)
94 {
95         // LordHavoc: added demo_nehahra cvar
96         Cvar_RegisterVariable (&demo_nehahra);
97         if (gamemode == GAME_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         FOG_clear(); // LordHavoc: no fog until set
247         R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
248         data = entdata;
249         if (!data)
250                 return;
251         data = COM_Parse(data);
252         if (!data)
253                 return; // error
254         if (com_token[0] != '{')
255                 return; // error
256         while (1)
257         {
258                 data = COM_Parse(data);
259                 if (!data)
260                         return; // error
261                 if (com_token[0] == '}')
262                         break; // end of worldspawn
263                 if (com_token[0] == '_')
264                         strcpy(key, com_token + 1);
265                 else
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("fog", key))
280                         sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
281                 else if (!strcmp("fog_density", key))
282                         fog_density = atof(value);
283                 else if (!strcmp("fog_red", key))
284                         fog_red = atof(value);
285                 else if (!strcmp("fog_green", key))
286                         fog_green = atof(value);
287                 else if (!strcmp("fog_blue", key))
288                         fog_blue = atof(value);
289         }
290 }
291
292 /*
293 //this code is going to be removed
294
295 #define MAX_STATICLIGHTS 2048
296 // tyrlite types
297 #define LIGHTFADE_LMINUSX 0 // light, arghlite, others?
298 #define LIGHTFADE_LDIVX 1
299 #define LIGHTFADE_LDIVX2 2 // hlight
300 #define LIGHTFADE_L 3
301 #define LIGHTFADE_DEFAULT 999999 // light util not yet identified, switched later
302
303 typedef struct
304 {
305         int fadetype; // one of the LIGHTFADE_ values
306         int style;
307         vec3_t origin;
308         vec_t distancescale; // attenuation
309
310         // spotlights
311         vec3_t direction; // direction
312         vec_t cone; // cone cosine, any light cosine outside this range is suddenly black
313
314         // LIGHTFADE_LMINUSX
315         vec_t light;
316         vec3_t color;
317
318         // LIGHTFADE_LDIVX and LIGHTFADE_LDIVX2
319         vec3_t light2; // light * color
320         vec_t lightsubtract; // hlight feature
321 }
322 staticlight_t;
323
324 extern staticlight_t staticlight[MAX_STATICLIGHTS];
325 extern int staticlights;
326
327 extern int r_sunlightenabled;
328 extern vec3_t r_sunlightdirection, r_sunlightcolor;
329 extern vec3_t r_light_ambientcolor;
330
331
332
333 staticlight_t staticlight[MAX_STATICLIGHTS];
334 int staticlights;
335
336 int r_sunlightenabled;
337 vec3_t r_sunlightdirection, r_sunlightcolor;
338 vec3_t r_light_ambientcolor;
339
340 void CL_ParseEntityLump(char *entdata)
341 {
342         char *data;
343         char key[128], value[4096];
344         char targetnamebuffer[65536];
345         char *targetname[8192], *target[MAX_STATICLIGHTS], light_target[256];
346         vec3_t targetnameorigin[8192], v;
347         int targets, targetnames, targetnamebufferpos, targetnameorigintofillin;
348         int i, j, n;
349         float f1, f2, f3, f4;
350         float ambientlight, ambientcolor[3], sunlight, sunlightdirection[3], sunlightcolor[3];
351         int light_fadetype, light_style, hlight, tyrlite, light_enable;
352         float light_origin[3], light_light, light_distancescale, light_lightcolor[3], light_color[3], light_direction[3], light_cone, light_lightradius;
353         FOG_clear(); // LordHavoc: no fog until set
354         R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
355         r_sunlightenabled = false;
356         staticlights = 0;
357         data = entdata;
358         if (!data)
359                 return;
360         data = COM_Parse(data);
361         if (!data)
362                 return; // error
363         if (com_token[0] != '{')
364                 return; // error
365         hlight = false;
366         tyrlite = false;
367         ambientlight = 0;
368         ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = 1;
369         sunlight = 0;
370         sunlightcolor[0] = sunlightcolor[1] = sunlightcolor[2] = 1;
371         sunlightdirection[0] = 0;
372         sunlightdirection[1] = 0;
373         sunlightdirection[2] = -1;
374         targets = 0;
375         targetnames = 0;
376         targetnamebufferpos = 0;
377         while (1)
378         {
379                 data = COM_Parse(data);
380                 if (!data)
381                         return; // error
382                 if (com_token[0] == '}')
383                         break; // end of worldspawn
384                 if (com_token[0] == '_')
385                         strcpy(key, com_token + 1);
386                 else
387                         strcpy(key, com_token);
388                 while (key[strlen(key)-1] == ' ') // remove trailing spaces
389                         key[strlen(key)-1] = 0;
390                 data = COM_Parse(data);
391                 if (!data)
392                         return; // error
393                 strcpy(value, com_token);
394                 if (!strcmp("sky", key))
395                         R_SetSkyBox(value);
396                 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
397                         R_SetSkyBox(value);
398                 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
399                         R_SetSkyBox(value);
400                 else if (!strcmp("fog", key))
401                         sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
402                 else if (!strcmp("fog_density", key))
403                         fog_density = atof(value);
404                 else if (!strcmp("fog_red", key))
405                         fog_red = atof(value);
406                 else if (!strcmp("fog_green", key))
407                         fog_green = atof(value);
408                 else if (!strcmp("fog_blue", key))
409                         fog_blue = atof(value);
410                 else if (!strcmp("light", key))
411                         ambientlight = atof(value);
412                 else if (!strcmp("sunlight", key))
413                 {
414                         sunlight = atof(value);
415                         tyrlite = true;
416                 }
417                 else if (!strcmp("sun_color", key))
418                 {
419                         if (sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
420                                 VectorCopy(v, sunlightcolor);
421                         tyrlite = true;
422                 }
423                 else if (!strcmp("sun_mangle", key))
424                 {
425                         if (sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
426                                 AngleVectors(v, sunlightdirection, NULL, NULL);
427                         tyrlite = true;
428                 }
429         }
430
431         if (sunlight)
432         {
433                 r_sunlightenabled = true;
434                 VectorScale(sunlightcolor, sunlight, r_sunlightcolor);
435                 VectorCopy(sunlightdirection, r_sunlightdirection);
436         }
437         VectorScale(ambientcolor, ambientlight, r_light_ambientcolor);
438
439         while(1)
440         {
441                 data = COM_Parse(data);
442                 if (!data)
443                         break; // done
444                 if (com_token[0] != '{')
445                         break; // error
446                 light_light = 0;
447                 VectorClear(light_origin);
448                 light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
449                 light_color[0] = light_color[1] = light_color[2] = 1.0f;
450                 light_direction[0] = light_direction[1] = light_direction[2] = 0.0f;
451                 light_cone = -cos(20*M_PI/180);
452                 light_distancescale = 1.0f;
453                 light_fadetype = LIGHTFADE_DEFAULT; // replaced later when light util is identified
454                 light_style = 0;
455                 light_lightradius = 0;
456                 light_enable = false;
457                 targetnameorigintofillin = -1;
458                 while (1)
459                 {
460                         data = COM_Parse(data);
461                         if (!data)
462                                 return; // error
463                         if (com_token[0] == '}')
464                                 break;
465                         if (com_token[0] == '_')
466                                 strcpy(key, com_token + 1);
467                         else
468                                 strcpy(key, com_token);
469                         while (key[strlen(key)-1] == ' ') // remove trailing spaces
470                                 key[strlen(key)-1] = 0;
471                         data = COM_Parse(data);
472                         if (!data)
473                                 return; // error
474                         strcpy(value, com_token);
475                         if (!strcmp("light", key))
476                         {
477                                 n = sscanf(value, "%f %f %f %f", &f1, &f2, &f3, &f4);
478                                 switch(n)
479                                 {
480                                 case 1:
481                                         // id light, arghlite, tyrlite, others
482                                         light_light = f1;
483                                         light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
484                                         break;
485                                 case 3:
486                                         // hlight specific (supports all 3 light formats, but this one is unique to it)
487                                         hlight = true;
488                                         light_light = max(f1, max(f2, f3));
489                                         light_lightcolor[0] = f1 / light_light;
490                                         light_lightcolor[1] = f2 / light_light;
491                                         light_lightcolor[2] = f3 / light_light;
492                                         break;
493                                 case 4:
494                                         // halflife
495                                         hlight = true; // unless this is a halflife map, probably hlight
496                                         light_light = f4;
497                                         light_lightcolor[0] = f1 * (1.0f / 255.0f);
498                                         light_lightcolor[1] = f1 * (1.0f / 255.0f);
499                                         light_lightcolor[2] = f1 * (1.0f / 255.0f);
500                                         break;
501                                 default:
502                                         // error
503                                         break;
504                                 }
505                         }
506                         else if (!strcmp("color", key))
507                         {
508                                 n = sscanf(value, "%f %f %f", &f1, &f2, &f3);
509                                 if (n == 3)
510                                 {
511                                         light_color[0] = f1;
512                                         light_color[1] = f2;
513                                         light_color[2] = f3;
514                                 }
515                                 // n != 3 is an error
516                         }
517                         else if (!strcmp("wait", key))
518                         {
519                                 light_distancescale = atof(value);
520                         }
521                         else if (!strcmp("delay", key))
522                         {
523                                 light_fadetype = atoi(value);
524                                 tyrlite = true;
525                         }
526                         else if (!strcmp("angle", key))
527                         {
528                                 light_cone = -cos(atof(value) * M_PI / 360);
529                         }
530                         else if (!strcmp("mangle", key))
531                         {
532                                 n = sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]);
533                                 if (n == 3)
534                                         AngleVectors(v, light_direction, NULL, NULL);
535                                 // n != 3 is an error
536                                 tyrlite = true;
537                         }
538                         else if (!strcmp("style", key))
539                         {
540                                 n = atoi(value);
541                                 if (n >= 0 && n < MAX_LIGHTSTYLES)
542                                         light_style = n;
543                         }
544                         else if (!strcmp("lightradius", key))
545                         {
546                                 hlight = true;
547                                 light_lightradius = atof(value);
548                         }
549                         else if (!strcmp("classname", key))
550                         {
551                                 if (!strncmp(value, "light", 5))
552                                         light_enable = true;
553                         }
554                         else if (!strcmp("origin", key))
555                         {
556                                 if (sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
557                                         VectorCopy(v, light_origin);
558                         }
559                         else if (!strcmp("targetname", key))
560                         {
561                                 if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
562                                 {
563                                         targetname[targetnames] = targetnamebuffer + targetnamebufferpos;
564                                         strcpy(targetnamebuffer + targetnamebufferpos, value);
565                                         targetnamebufferpos += strlen(value) + 1;
566                                         targetnameorigintofillin = targetnames++;
567                                 }
568                         }
569                         else if (!strcmp("target", key))
570                                 if (strlen(value) < sizeof(light_target))
571                                         strcpy(light_target, value);
572                 }
573                 if (targetnameorigintofillin >= 0)
574                         VectorCopy(light_origin, targetnameorigin[targetnameorigintofillin]);
575                 if (light_enable && staticlights < MAX_STATICLIGHTS && light_light != 0)
576                 {
577                         if (light_target[0] && (targets < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
578                         {
579                                 target[staticlights] = targetnamebuffer + targetnamebufferpos;
580                                 strcpy(targetnamebuffer + targetnamebufferpos, value);
581                                 targetnamebufferpos += strlen(value) + 1;
582                         }
583                         else
584                                 target[staticlights] = NULL;
585
586                         staticlight[staticlights].fadetype = light_fadetype;
587                         staticlight[staticlights].style = light_style;
588                         VectorCopy(light_origin, staticlight[staticlights].origin);
589                         staticlight[staticlights].distancescale = light_distancescale;
590                         // these are often altered later by the target name linking
591                         VectorCopy(light_direction, staticlight[staticlights].direction);
592                         staticlight[staticlights].cone = light_cone;
593
594                         staticlight[staticlights].light = light_light;
595                         staticlight[staticlights].color[0] = light_lightcolor[0] * light_color[0];
596                         staticlight[staticlights].color[1] = light_lightcolor[1] * light_color[1];
597                         staticlight[staticlights].color[2] = light_lightcolor[2] * light_color[2];
598
599                         staticlight[staticlights].light2[0] = light_light * light_lightcolor[0] * light_color[0];
600                         staticlight[staticlights].light2[1] = light_light * light_lightcolor[1] * light_color[1];
601                         staticlight[staticlights].light2[2] = light_light * light_lightcolor[2] * light_color[2];
602                         staticlight[staticlights].lightsubtract = 0;
603                         if (light_lightradius)
604                         {
605                                 staticlight[staticlights].fadetype = LIGHTFADE_LDIVX2;
606                                 staticlight[staticlights].lightsubtract = max(staticlight[staticlights].color[0], max(staticlight[staticlights].color[1], staticlight[staticlights].color[2])) * 0.5f / (light_lightradius * light_distancescale * light_lightradius * light_distancescale * (1.0f / 65536.0f) + 1.0f);
607                         }
608                         staticlights++;
609                 }
610         }
611         if (cl.worldmodel->ishlbsp)
612                 n = LIGHTFADE_LDIVX2;
613         else if (light_hlight.integer)
614                 n = LIGHTFADE_LDIVX2;
615         else if (tyrlite)
616                 n = LIGHTFADE_LMINUSX;
617         else if (hlight)
618                 n = LIGHTFADE_LDIVX2;
619         else
620                 n = LIGHTFADE_LMINUSX;
621         for (i = 0;i < staticlights;i++)
622         {
623                 if (staticlight[i].fadetype == LIGHTFADE_DEFAULT)
624                         staticlight[i].fadetype = n;
625                 if (target[i])
626                 {
627                         for (j = 0;j < targetnames;j++)
628                         {
629                                 if (!strcmp(target[i], targetname[j]))
630                                 {
631                                         VectorSubtract(targetnameorigin[j], staticlight[i].origin, v);
632                                         VectorNormalize(v);
633                                         VectorCopy(v, staticlight[i].direction);
634                                         break;
635                                 }
636                         }
637                 }
638                 if (staticlight[i].direction[0] == 0 && staticlight[i].direction[1] == 0 && staticlight[i].direction[2] == 0)
639                         staticlight[i].cone = 0;
640         }
641 }
642 */
643
644 /*
645 =====================
646 CL_SignonReply
647
648 An svc_signonnum has been received, perform a client side setup
649 =====================
650 */
651 static void CL_SignonReply (void)
652 {
653         char    str[8192];
654
655 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
656
657         switch (cls.signon)
658         {
659         case 1:
660                 MSG_WriteByte (&cls.message, clc_stringcmd);
661                 MSG_WriteString (&cls.message, "prespawn");
662                 break;
663
664         case 2:
665                 MSG_WriteByte (&cls.message, clc_stringcmd);
666                 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
667
668                 MSG_WriteByte (&cls.message, clc_stringcmd);
669                 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
670
671                 if (cl_pmodel.integer)
672                 {
673                         MSG_WriteByte (&cls.message, clc_stringcmd);
674                         MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
675                 }
676
677                 MSG_WriteByte (&cls.message, clc_stringcmd);
678                 sprintf (str, "spawn %s", cls.spawnparms);
679                 MSG_WriteString (&cls.message, str);
680                 break;
681
682         case 3:
683                 MSG_WriteByte (&cls.message, clc_stringcmd);
684                 MSG_WriteString (&cls.message, "begin");
685                 break;
686
687         case 4:
688 //              SCR_EndLoadingPlaque ();                // allow normal screen updates
689                 Con_ClearNotify();
690                 break;
691         }
692 }
693
694 /*
695 ==================
696 CL_ParseServerInfo
697 ==================
698 */
699 void CL_ParseServerInfo (void)
700 {
701         char    *str;
702         int             i;
703         int             nummodels, numsounds;
704         char    model_precache[MAX_MODELS][MAX_QPATH];
705         char    sound_precache[MAX_SOUNDS][MAX_QPATH];
706
707         Con_DPrintf ("Serverinfo packet received.\n");
708 //
709 // wipe the client_state_t struct
710 //
711         CL_ClearState ();
712
713 // parse protocol version number
714         i = MSG_ReadLong ();
715         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
716         {
717                 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
718                 return;
719         }
720         Nehahrademcompatibility = false;
721         if (i == 250)
722                 Nehahrademcompatibility = true;
723         if (cls.demoplayback && demo_nehahra.integer)
724                 Nehahrademcompatibility = true;
725         dpprotocol = i == DPPROTOCOL_VERSION;
726
727 // parse maxclients
728         cl.maxclients = MSG_ReadByte ();
729         if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
730         {
731                 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
732                 return;
733         }
734         cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
735
736 // parse gametype
737         cl.gametype = MSG_ReadByte ();
738
739 // parse signon message
740         str = MSG_ReadString ();
741         strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
742
743 // seperate the printfs so the server message can have a color
744         if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
745         {
746                 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");
747                 Con_Printf ("%c%s\n", 2, str);
748         }
749
750 //
751 // first we go through and touch all of the precache data that still
752 // happens to be in the cache, so precaching something else doesn't
753 // needlessly purge it
754 //
755
756         Mem_CheckSentinelsGlobal();
757
758         Mod_ClearUsed();
759
760         Mem_CheckSentinelsGlobal();
761
762 // precache models
763         memset (cl.model_precache, 0, sizeof(cl.model_precache));
764         for (nummodels=1 ; ; nummodels++)
765         {
766                 str = MSG_ReadString ();
767                 if (!str[0])
768                         break;
769                 if (nummodels==MAX_MODELS)
770                 {
771                         Con_Printf ("Server sent too many model precaches\n");
772                         return;
773                 }
774                 if (strlen(str) >= MAX_QPATH)
775                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
776                 strcpy (model_precache[nummodels], str);
777                 Mod_TouchModel (str);
778         }
779
780 // precache sounds
781         memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
782         for (numsounds=1 ; ; numsounds++)
783         {
784                 str = MSG_ReadString ();
785                 if (!str[0])
786                         break;
787                 if (numsounds==MAX_SOUNDS)
788                 {
789                         Con_Printf ("Server sent too many sound precaches\n");
790                         return;
791                 }
792                 if (strlen(str) >= MAX_QPATH)
793                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
794                 strcpy (sound_precache[numsounds], str);
795                 S_TouchSound (str);
796         }
797
798         Mem_CheckSentinelsGlobal();
799
800         Mod_PurgeUnused();
801
802 //
803 // now we try to load everything else until a cache allocation fails
804 //
805
806         Mem_CheckSentinelsGlobal();
807
808         for (i=1 ; i<nummodels ; i++)
809         {
810                 // LordHavoc: i == 1 means the first model is the world model
811                 cl.model_precache[i] = Mod_ForName (model_precache[i], false, true, i == 1);
812
813                 if (cl.model_precache[i] == NULL)
814                 {
815                         Con_Printf("Model %s not found\n", model_precache[i]);
816                         return;
817                 }
818                 CL_KeepaliveMessage ();
819         }
820
821         Mem_CheckSentinelsGlobal();
822
823         S_BeginPrecaching ();
824         for (i=1 ; i<numsounds ; i++)
825         {
826                 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
827                 CL_KeepaliveMessage ();
828         }
829         S_EndPrecaching ();
830
831 // local state
832         cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
833         cl_entities[0].render.scale = 1;
834         cl_entities[0].render.alpha = 1;
835
836         R_NewMap ();
837
838         Mem_CheckSentinelsGlobal();
839
840         noclip_anglehack = false;               // noclip is turned off at start
841 }
842
843 void CL_ValidateState(entity_state_t *s)
844 {
845         model_t *model;
846
847         if (!s->active)
848                 return;
849
850         if (s->modelindex >= MAX_MODELS)
851                 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
852
853         // colormap is client index + 1
854         if (s->colormap > cl.maxclients)
855                 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
856
857         model = cl.model_precache[s->modelindex];
858         Mod_CheckLoaded(model);
859         if (model && s->frame >= model->numframes)
860         {
861                 Con_Printf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
862                 s->frame = 0;
863         }
864         if (model && s->skin > 0 && s->skin >= model->numskins)
865         {
866                 Con_Printf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
867                 s->skin = 0;
868         }
869 }
870
871 /*
872 ==================
873 CL_ParseUpdate
874
875 Parse an entity update message from the server
876 If an entities model or origin changes from frame to frame, it must be
877 relinked.  Other attributes can change without relinking.
878 ==================
879 */
880 byte entkill[MAX_EDICTS];
881 int bitprofile[32], bitprofilecount = 0;
882 void CL_ParseUpdate (int bits)
883 {
884         int i, num, deltadie;
885         entity_t *ent;
886         entity_state_t new;
887
888         if (cls.signon == SIGNONS - 1)
889         {       // first update is the final signon stage
890                 cls.signon = SIGNONS;
891                 CL_SignonReply ();
892         }
893
894         if (bits & U_MOREBITS)
895                 bits |= (MSG_ReadByte()<<8);
896         if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
897         {
898                 bits |= MSG_ReadByte() << 16;
899                 if (bits & U_EXTEND2)
900                         bits |= MSG_ReadByte() << 24;
901         }
902
903         if (bits & U_LONGENTITY)
904                 num = (unsigned) MSG_ReadShort ();
905         else
906                 num = (unsigned) MSG_ReadByte ();
907
908         if (num >= MAX_EDICTS)
909                 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
910         if (num < 1)
911                 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
912
913         // mark as visible (no kill)
914         entkill[num] = 0;
915
916         ent = CL_EntityNum (num);
917
918         for (i = 0;i < 32;i++)
919                 if (bits & (1 << i))
920                         bitprofile[i]++;
921         bitprofilecount++;
922
923         deltadie = false;
924         if (bits & U_DELTA)
925         {
926                 new = ent->state_current;
927                 if (!new.active)
928                         deltadie = true; // was not present in previous frame, leave hidden until next full update
929         }
930         else
931                 new = ent->state_baseline;
932
933         new.time = cl.mtime[0];
934
935         new.flags = 0;
936         new.active = true;
937         if (bits & U_MODEL)             new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
938         if (bits & U_FRAME)             new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
939         if (bits & U_COLORMAP)  new.colormap = MSG_ReadByte();
940         if (bits & U_SKIN)              new.skin = MSG_ReadByte();
941         if (bits & U_EFFECTS)   new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
942         if (bits & U_ORIGIN1)   new.origin[0] = MSG_ReadCoord();
943         if (bits & U_ANGLE1)    new.angles[0] = MSG_ReadAngle();
944         if (bits & U_ORIGIN2)   new.origin[1] = MSG_ReadCoord();
945         if (bits & U_ANGLE2)    new.angles[1] = MSG_ReadAngle();
946         if (bits & U_ORIGIN3)   new.origin[2] = MSG_ReadCoord();
947         if (bits & U_ANGLE3)    new.angles[2] = MSG_ReadAngle();
948         if (bits & U_STEP)              new.flags |= RENDER_STEP;
949         if (bits & U_ALPHA)             new.alpha = MSG_ReadByte();
950         if (bits & U_SCALE)             new.scale = MSG_ReadByte();
951         if (bits & U_EFFECTS2)  new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
952         if (bits & U_GLOWSIZE)  new.glowsize = MSG_ReadByte();
953         if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
954 #if 0
955         if (bits & U_COLORMOD)  {int i = MSG_ReadByte();float r = (((int) i >> 5) & 7) * 1.0 / 7, g = (((int) i >> 2) & 7) * 1.0 / 7, b = ((int) i & 3) * 1.0 / 3;Con_Printf("warning: U_COLORMOD %i (%1.2f %1.2f %1.2f) ignored\n", i, r, g, b);}
956 #else
957         // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
958         if (bits & U_COLORMOD)  MSG_ReadByte();
959 #endif
960         if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
961         if (bits & U_FRAME2)    new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
962         if (bits & U_MODEL2)    new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
963         if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
964         if (bits & U_EXTERIORMODEL)     new.flags |= RENDER_EXTERIORMODEL;
965
966         // LordHavoc: to allow playback of the Nehahra movie
967         if (Nehahrademcompatibility && (bits & U_EXTEND1))
968         {
969                 // LordHavoc: evil format
970                 int i = MSG_ReadFloat();
971                 int j = MSG_ReadFloat() * 255.0f;
972                 if (i == 2)
973                 {
974                         if (MSG_ReadFloat())
975                                 new.effects |= EF_FULLBRIGHT;
976                 }
977                 if (j < 0)
978                         new.alpha = 0;
979                 else if (j == 0 || j >= 255)
980                         new.alpha = 255;
981                 else
982                         new.alpha = j;
983         }
984
985         if (deltadie)
986         {
987                 // hide the entity
988                 new.active = false;
989         }
990         else
991                 CL_ValidateState(&new);
992
993         if (new.flags & RENDER_STEP) // FIXME: rename this flag?
994         {
995                 // make time identical for memcmp
996                 new.time = ent->state_current.time;
997                 if (memcmp(&new, &ent->state_current, sizeof(entity_state_t)))
998                 {
999                         // state has changed
1000                         ent->state_previous = ent->state_current;
1001                         ent->state_current = new;
1002                         // assume 10fps animation
1003                         ent->state_previous.time = cl.mtime[0];
1004                         ent->state_current.time = cl.mtime[0] + 0.1; //ent->state_previous.time + 0.1;
1005                 }
1006         }
1007         else
1008         {
1009                 ent->state_previous = ent->state_current;
1010                 ent->state_current = new;
1011         }
1012 }
1013
1014 char *bitprofilenames[32] =
1015 {
1016         "U_MOREBITS",
1017         "U_ORIGIN1",
1018         "U_ORIGIN2",
1019         "U_ORIGIN3",
1020         "U_ANGLE2",
1021         "U_STEP",
1022         "U_FRAME",
1023         "U_SIGNAL",
1024         "U_ANGLE1",
1025         "U_ANGLE3",
1026         "U_MODEL",
1027         "U_COLORMAP",
1028         "U_SKIN",
1029         "U_EFFECTS",
1030         "U_LONGENTITY",
1031         "U_EXTEND1",
1032         "U_DELTA",
1033         "U_ALPHA",
1034         "U_SCALE",
1035         "U_EFFECTS2",
1036         "U_GLOWSIZE",
1037         "U_GLOWCOLOR",
1038         "obsolete U_COLORMOD",
1039         "U_EXTEND2",
1040         "U_GLOWTRAIL",
1041         "U_VIEWMODEL",
1042         "U_FRAME2",
1043         "U_MODEL2",
1044         "U_EXTERIORMODEL",
1045         "U_UNUSED29",
1046         "U_UNUSED30",
1047         "U_EXTEND3",
1048 };
1049
1050 void CL_BitProfile_f(void)
1051 {
1052         int i;
1053         Con_Printf("bitprofile: %i updates\n");
1054         if (bitprofilecount)
1055                 for (i = 0;i < 32;i++)
1056 //                      if (bitprofile[i])
1057                                 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
1058         Con_Printf("\n");
1059         for (i = 0;i < 32;i++)
1060                 bitprofile[i] = 0;
1061         bitprofilecount = 0;
1062 }
1063
1064 void CL_EntityUpdateSetup(void)
1065 {
1066         memset(entkill, 1, MAX_EDICTS);
1067 }
1068
1069 void CL_EntityUpdateEnd(void)
1070 {
1071         int i;
1072         for (i = 1;i < MAX_EDICTS;i++)
1073                 if (entkill[i])
1074                         cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
1075 }
1076
1077 /*
1078 ==================
1079 CL_ParseBaseline
1080 ==================
1081 */
1082 void CL_ParseBaseline (entity_t *ent, int large)
1083 {
1084         int i;
1085
1086         memset(&ent->state_baseline, 0, sizeof(entity_state_t));
1087         ent->state_baseline.active = true;
1088         if (large)
1089         {
1090                 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
1091                 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
1092         }
1093         else
1094         {
1095                 ent->state_baseline.modelindex = MSG_ReadByte ();
1096                 ent->state_baseline.frame = MSG_ReadByte ();
1097         }
1098         ent->state_baseline.colormap = MSG_ReadByte();
1099         ent->state_baseline.skin = MSG_ReadByte();
1100         for (i = 0;i < 3;i++)
1101         {
1102                 ent->state_baseline.origin[i] = MSG_ReadCoord ();
1103                 ent->state_baseline.angles[i] = MSG_ReadAngle ();
1104         }
1105         ent->state_baseline.alpha = 255;
1106         ent->state_baseline.scale = 16;
1107         ent->state_baseline.glowsize = 0;
1108         ent->state_baseline.glowcolor = 254;
1109         ent->state_previous = ent->state_current = ent->state_baseline;
1110
1111         CL_ValidateState(&ent->state_baseline);
1112 }
1113
1114
1115 /*
1116 ==================
1117 CL_ParseClientdata
1118
1119 Server information pertaining to this client only
1120 ==================
1121 */
1122 void CL_ParseClientdata (int bits)
1123 {
1124         int i, j;
1125
1126         bits &= 0xFFFF;
1127         if (bits & SU_EXTEND1)
1128                 bits |= (MSG_ReadByte() << 16);
1129         if (bits & SU_EXTEND2)
1130                 bits |= (MSG_ReadByte() << 24);
1131
1132         if (bits & SU_VIEWHEIGHT)
1133                 cl.viewheight = MSG_ReadChar ();
1134         else
1135                 cl.viewheight = DEFAULT_VIEWHEIGHT;
1136
1137         if (bits & SU_IDEALPITCH)
1138                 cl.idealpitch = MSG_ReadChar ();
1139         else
1140                 cl.idealpitch = 0;
1141         
1142         VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
1143         for (i=0 ; i<3 ; i++)
1144         {
1145                 if (bits & (SU_PUNCH1<<i) )
1146                 {
1147                         if (dpprotocol)
1148                                 cl.punchangle[i] = MSG_ReadPreciseAngle();
1149                         else
1150                                 cl.punchangle[i] = MSG_ReadChar();
1151                 }
1152                 else
1153                         cl.punchangle[i] = 0;
1154                 if (bits & (SU_PUNCHVEC1<<i))
1155                         cl.punchvector[i] = MSG_ReadFloatCoord();
1156                 else
1157                         cl.punchvector[i] = 0;
1158                 if (bits & (SU_VELOCITY1<<i) )
1159                         cl.mvelocity[0][i] = MSG_ReadChar()*16;
1160                 else
1161                         cl.mvelocity[0][i] = 0;
1162         }
1163
1164         i = MSG_ReadLong ();
1165         if (cl.items != i)
1166         {       // set flash times
1167                 for (j=0 ; j<32 ; j++)
1168                         if ( (i & (1<<j)) && !(cl.items & (1<<j)))
1169                                 cl.item_gettime[j] = cl.time;
1170                 cl.items = i;
1171         }
1172                 
1173         cl.onground = (bits & SU_ONGROUND) != 0;
1174         cl.inwater = (bits & SU_INWATER) != 0;
1175
1176         cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
1177         cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
1178         cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
1179         cl.stats[STAT_HEALTH] = MSG_ReadShort();
1180         cl.stats[STAT_AMMO] = MSG_ReadByte();
1181
1182         cl.stats[STAT_SHELLS] = MSG_ReadByte();
1183         cl.stats[STAT_NAILS] = MSG_ReadByte();
1184         cl.stats[STAT_ROCKETS] = MSG_ReadByte();
1185         cl.stats[STAT_CELLS] = MSG_ReadByte();
1186
1187         i = MSG_ReadByte ();
1188
1189         if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
1190                 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
1191         else
1192                 cl.stats[STAT_ACTIVEWEAPON] = i;
1193 }
1194
1195 /*
1196 =====================
1197 CL_ParseStatic
1198 =====================
1199 */
1200 void CL_ParseStatic (int large)
1201 {
1202         entity_t *ent;
1203
1204         if (cl.num_statics >= MAX_STATIC_ENTITIES)
1205                 Host_Error ("Too many static entities");
1206         ent = &cl_static_entities[cl.num_statics++];
1207         CL_ParseBaseline (ent, large);
1208
1209 // copy it to the current state
1210         ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
1211         ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
1212         ent->render.framelerp = 0;
1213         // make torchs play out of sync
1214         ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
1215         ent->render.colormap = -1; // no special coloring
1216         ent->render.skinnum = ent->state_baseline.skin;
1217         ent->render.effects = ent->state_baseline.effects;
1218         ent->render.alpha = 1;
1219         ent->render.scale = 1;
1220         ent->render.alpha = 1;
1221
1222         VectorCopy (ent->state_baseline.origin, ent->render.origin);
1223         VectorCopy (ent->state_baseline.angles, ent->render.angles);    
1224 }
1225
1226 /*
1227 ===================
1228 CL_ParseStaticSound
1229 ===================
1230 */
1231 void CL_ParseStaticSound (int large)
1232 {
1233         vec3_t          org;
1234         int                     sound_num, vol, atten;
1235
1236         MSG_ReadVector(org);
1237         if (large)
1238                 sound_num = (unsigned short) MSG_ReadShort ();
1239         else
1240                 sound_num = MSG_ReadByte ();
1241         vol = MSG_ReadByte ();
1242         atten = MSG_ReadByte ();
1243         
1244         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
1245 }
1246
1247 void CL_ParseEffect (void)
1248 {
1249         vec3_t          org;
1250         int                     modelindex, startframe, framecount, framerate;
1251
1252         MSG_ReadVector(org);
1253         modelindex = MSG_ReadByte ();
1254         startframe = MSG_ReadByte ();
1255         framecount = MSG_ReadByte ();
1256         framerate = MSG_ReadByte ();
1257
1258         CL_Effect(org, modelindex, startframe, framecount, framerate);
1259 }
1260
1261 void CL_ParseEffect2 (void)
1262 {
1263         vec3_t          org;
1264         int                     modelindex, startframe, framecount, framerate;
1265
1266         MSG_ReadVector(org);
1267         modelindex = MSG_ReadShort ();
1268         startframe = MSG_ReadShort ();
1269         framecount = MSG_ReadByte ();
1270         framerate = MSG_ReadByte ();
1271
1272         CL_Effect(org, modelindex, startframe, framecount, framerate);
1273 }
1274
1275
1276 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1277
1278 /*
1279 =====================
1280 CL_ParseServerMessage
1281 =====================
1282 */
1283 void CL_ParseServerMessage (void)
1284 {
1285         int                     cmd;
1286         int                     i, entitiesupdated;
1287         byte            cmdlog[32];
1288         char            *cmdlogname[32], *temp;
1289         int                     cmdindex, cmdcount = 0;
1290         
1291 //
1292 // if recording demos, copy the message out
1293 //
1294         if (cl_shownet.integer == 1)
1295                 Con_Printf ("%i ",net_message.cursize);
1296         else if (cl_shownet.integer == 2)
1297                 Con_Printf ("------------------\n");
1298         
1299         cl.onground = false;    // unless the server says otherwise     
1300 //
1301 // parse the message
1302 //
1303         MSG_BeginReading ();
1304
1305         entitiesupdated = false;
1306         CL_EntityUpdateSetup();
1307         
1308         while (1)
1309         {
1310                 if (msg_badread)
1311                         Host_Error ("CL_ParseServerMessage: Bad server message");
1312
1313                 cmd = MSG_ReadByte ();
1314
1315                 if (cmd == -1)
1316                 {
1317                         SHOWNET("END OF MESSAGE");
1318                         break;          // end of message
1319                 }
1320
1321                 cmdindex = cmdcount & 31;
1322                 cmdcount++;
1323                 cmdlog[cmdindex] = cmd;
1324
1325                 // if the high bit of the command byte is set, it is a fast update
1326                 if (cmd & 128)
1327                 {
1328                         // 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)
1329                         temp = "entity";
1330                         cmdlogname[cmdindex] = temp;
1331                         SHOWNET("fast update");
1332                         CL_ParseUpdate (cmd&127);
1333                         continue;
1334                 }
1335
1336                 SHOWNET(svc_strings[cmd]);
1337                 cmdlogname[cmdindex] = svc_strings[cmd];
1338                 if (!cmdlogname[cmdindex])
1339                 {
1340                         // 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)
1341                         temp = "<unknown>";
1342                         cmdlogname[cmdindex] = temp;
1343                 }
1344         
1345                 // other commands
1346                 switch (cmd)
1347                 {
1348                 default:
1349                         {
1350                                 char description[32*64], temp[64];
1351                                 int count;
1352                                 strcpy(description, "packet dump: ");
1353                                 i = cmdcount - 32;
1354                                 if (i < 0)
1355                                         i = 0;
1356                                 count = cmdcount - i;
1357                                 i &= 31;
1358                                 while(count > 0)
1359                                 {
1360                                         sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1361                                         strcat(description, temp);
1362                                         count--;
1363                                         i++;
1364                                         i &= 31;
1365                                 }
1366                                 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1367                                 Con_Printf("%s", description);
1368                                 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1369                         }
1370                         break;
1371                         
1372                 case svc_nop:
1373 //                      Con_Printf ("svc_nop\n");
1374                         break;
1375                         
1376                 case svc_time:
1377                         // handle old protocols which do not have entity update ranges
1378                         entitiesupdated = true;
1379                         cl.mtime[1] = cl.mtime[0];
1380                         cl.mtime[0] = MSG_ReadFloat ();                 
1381                         break;
1382
1383                 case svc_clientdata:
1384                         i = MSG_ReadShort ();
1385                         CL_ParseClientdata (i);
1386                         break;
1387                 
1388                 case svc_version:
1389                         i = MSG_ReadLong ();
1390                         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
1391                                 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
1392                         Nehahrademcompatibility = false;
1393                         if (i == 250)
1394                                 Nehahrademcompatibility = true;
1395                         if (cls.demoplayback && demo_nehahra.integer)
1396                                 Nehahrademcompatibility = true;
1397                         dpprotocol = i == DPPROTOCOL_VERSION;
1398                         break;
1399                         
1400                 case svc_disconnect:
1401                         Host_EndGame ("Server disconnected\n");
1402
1403                 case svc_print:
1404                         Con_Printf ("%s", MSG_ReadString ());
1405                         break;
1406                         
1407                 case svc_centerprint:
1408                         SCR_CenterPrint (MSG_ReadString ());
1409                         break;
1410                         
1411                 case svc_stufftext:
1412                         Cbuf_AddText (MSG_ReadString ());
1413                         break;
1414
1415                 case svc_damage:
1416                         V_ParseDamage ();
1417                         break;
1418
1419                 case svc_serverinfo:
1420                         CL_ParseServerInfo ();
1421 //                      vid.recalc_refdef = true;       // leave intermission full screen
1422                         break;
1423                         
1424                 case svc_setangle:
1425                         for (i=0 ; i<3 ; i++)
1426                                 cl.viewangles[i] = MSG_ReadAngle ();
1427                         break;
1428                         
1429                 case svc_setview:
1430                         cl.viewentity = MSG_ReadShort ();
1431                         break;
1432                                         
1433                 case svc_lightstyle:
1434                         i = MSG_ReadByte ();
1435                         if (i >= MAX_LIGHTSTYLES)
1436                                 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1437                         strncpy (cl_lightstyle[i].map,  MSG_ReadString(), MAX_STYLESTRING - 1);
1438                         cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1439                         cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1440                         break;
1441                         
1442                 case svc_sound:
1443                         CL_ParseStartSoundPacket(false);
1444                         break;
1445
1446                 case svc_sound2:
1447                         CL_ParseStartSoundPacket(true);
1448                         break;
1449
1450                 case svc_stopsound:
1451                         i = MSG_ReadShort();
1452                         S_StopSound(i>>3, i&7);
1453                         break;
1454
1455                 case svc_updatename:
1456                         i = MSG_ReadByte ();
1457                         if (i >= cl.maxclients)
1458                                 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1459                         strcpy (cl.scores[i].name, MSG_ReadString ());
1460                         break;
1461                         
1462                 case svc_updatefrags:
1463                         i = MSG_ReadByte ();
1464                         if (i >= cl.maxclients)
1465                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1466                         cl.scores[i].frags = MSG_ReadShort ();
1467                         break;                  
1468
1469                 case svc_updatecolors:
1470                         i = MSG_ReadByte ();
1471                         if (i >= cl.maxclients)
1472                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1473                         cl.scores[i].colors = MSG_ReadByte ();
1474                         break;
1475                         
1476                 case svc_particle:
1477                         CL_ParseParticleEffect ();
1478                         break;
1479
1480                 case svc_effect:
1481                         CL_ParseEffect ();
1482                         break;
1483
1484                 case svc_effect2:
1485                         CL_ParseEffect2 ();
1486                         break;
1487
1488                 case svc_spawnbaseline:
1489                         i = MSG_ReadShort ();
1490                         // must use CL_EntityNum() to force cl.num_entities up
1491                         CL_ParseBaseline (CL_EntityNum(i), false);
1492                         break;
1493                 case svc_spawnbaseline2:
1494                         i = MSG_ReadShort ();
1495                         // must use CL_EntityNum() to force cl.num_entities up
1496                         CL_ParseBaseline (CL_EntityNum(i), true);
1497                         break;
1498                 case svc_spawnstatic:
1499                         CL_ParseStatic (false);
1500                         break;
1501                 case svc_spawnstatic2:
1502                         CL_ParseStatic (true);
1503                         break;
1504                 case svc_temp_entity:
1505                         CL_ParseTEnt ();
1506                         break;
1507
1508                 case svc_setpause:
1509                         cl.paused = MSG_ReadByte ();
1510                         if (cl.paused)
1511                                 CDAudio_Pause ();
1512                         else
1513                                 CDAudio_Resume ();
1514                         break;
1515                         
1516                 case svc_signonnum:
1517                         i = MSG_ReadByte ();
1518                         if (i <= cls.signon)
1519                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
1520                         cls.signon = i;
1521                         CL_SignonReply ();
1522                         break;
1523
1524                 case svc_killedmonster:
1525                         cl.stats[STAT_MONSTERS]++;
1526                         break;
1527
1528                 case svc_foundsecret:
1529                         cl.stats[STAT_SECRETS]++;
1530                         break;
1531
1532                 case svc_updatestat:
1533                         i = MSG_ReadByte ();
1534                         if (i < 0 || i >= MAX_CL_STATS)
1535                                 Host_Error ("svc_updatestat: %i is invalid", i);
1536                         cl.stats[i] = MSG_ReadLong ();
1537                         break;
1538                         
1539                 case svc_spawnstaticsound:
1540                         CL_ParseStaticSound (false);
1541                         break;
1542
1543                 case svc_spawnstaticsound2:
1544                         CL_ParseStaticSound (true);
1545                         break;
1546
1547                 case svc_cdtrack:
1548                         cl.cdtrack = MSG_ReadByte ();
1549                         cl.looptrack = MSG_ReadByte ();
1550                         if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1551                                 CDAudio_Play ((byte)cls.forcetrack, true);
1552                         else
1553                                 CDAudio_Play ((byte)cl.cdtrack, true);
1554                         break;
1555
1556                 case svc_intermission:
1557                         cl.intermission = 1;
1558                         cl.completed_time = cl.time;
1559 //                      vid.recalc_refdef = true;       // go to full screen
1560                         break;
1561
1562                 case svc_finale:
1563                         cl.intermission = 2;
1564                         cl.completed_time = cl.time;
1565 //                      vid.recalc_refdef = true;       // go to full screen
1566                         SCR_CenterPrint (MSG_ReadString ());
1567                         break;
1568
1569                 case svc_cutscene:
1570                         cl.intermission = 3;
1571                         cl.completed_time = cl.time;
1572 //                      vid.recalc_refdef = true;       // go to full screen
1573                         SCR_CenterPrint (MSG_ReadString ());                    
1574                         break;
1575
1576                 case svc_sellscreen:
1577                         Cmd_ExecuteString ("help", src_command);
1578                         break;
1579                 case svc_hidelmp:
1580                         SHOWLMP_decodehide();
1581                         break;
1582                 case svc_showlmp:
1583                         SHOWLMP_decodeshow();
1584                         break;
1585                 case svc_skybox:
1586                         R_SetSkyBox(MSG_ReadString());
1587                         break;
1588                 }
1589         }
1590
1591         if (entitiesupdated)
1592                 CL_EntityUpdateEnd();
1593 }