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