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