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