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