]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - cl_parse.c
***map loader generates portals for the map*** (can you tell this is a big deal? :)
[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                         j = 0;
297                         for (i = 0;i < 4096;i++)
298                                 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
299                                         break;
300                         if (value[i])
301                         {
302                                 for (;i < 4096;i++)
303                                 {
304                                         // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
305                                         if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
306                                                 j = i+1;
307                                         else if (value[i] == ';' || value[i] == 0)
308                                         {
309                                                 k = value[i];
310                                                 value[i] = 0;
311                                                 strcpy(wadname, "textures/");
312                                                 strcat(wadname, &value[j]);
313                                                 W_LoadTextureWadFile (wadname, false);
314                                                 j = i+1;
315                                                 if (!k)
316                                                         break;
317                                         }
318                                 }
319                         }
320                 }
321         }
322 }
323
324 /*
325 ==================
326 CL_ParseServerInfo
327 ==================
328 */
329 extern cvar_t demo_nehahra;
330 void CL_ParseServerInfo (void)
331 {
332         char    *str;
333         int             i;
334         int             nummodels, numsounds;
335         char    model_precache[MAX_MODELS][MAX_QPATH];
336         char    sound_precache[MAX_SOUNDS][MAX_QPATH];
337         
338         Con_DPrintf ("Serverinfo packet received.\n");
339 //
340 // wipe the client_state_t struct
341 //
342         CL_ClearState ();
343
344 // parse protocol version number
345         i = MSG_ReadLong ();
346         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
347         {
348                 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
349                 return;
350         }
351         Nehahrademcompatibility = false;
352         if (i == 250)
353                 Nehahrademcompatibility = true;
354         if (cls.demoplayback && demo_nehahra.value)
355                 Nehahrademcompatibility = true;
356         dpprotocol = i == DPPROTOCOL_VERSION;
357
358 // parse maxclients
359         cl.maxclients = MSG_ReadByte ();
360         if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
361         {
362                 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
363                 return;
364         }
365         cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
366
367 // parse gametype
368         cl.gametype = MSG_ReadByte ();
369
370 // parse signon message
371         str = MSG_ReadString ();
372         strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
373
374 // seperate the printfs so the server message can have a color
375         if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
376         {
377                 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");
378                 Con_Printf ("%c%s\n", 2, str);
379         }
380
381 //
382 // first we go through and touch all of the precache data that still
383 // happens to be in the cache, so precaching something else doesn't
384 // needlessly purge it
385 //
386
387 // precache models
388         memset (cl.model_precache, 0, sizeof(cl.model_precache));
389         for (nummodels=1 ; ; nummodels++)
390         {
391                 str = MSG_ReadString ();
392                 if (!str[0])
393                         break;
394                 if (nummodels==MAX_MODELS)
395                 {
396                         Con_Printf ("Server sent too many model precaches\n");
397                         return;
398                 }
399                 if (strlen(str) >= MAX_QPATH)
400                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
401                 strcpy (model_precache[nummodels], str);
402                 Mod_TouchModel (str);
403         }
404
405 // precache sounds
406         memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
407         for (numsounds=1 ; ; numsounds++)
408         {
409                 str = MSG_ReadString ();
410                 if (!str[0])
411                         break;
412                 if (numsounds==MAX_SOUNDS)
413                 {
414                         Con_Printf ("Server sent too many sound precaches\n");
415                         return;
416                 }
417                 if (strlen(str) >= MAX_QPATH)
418                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
419                 strcpy (sound_precache[numsounds], str);
420                 S_TouchSound (str);
421         }
422
423 //
424 // now we try to load everything else until a cache allocation fails
425 //
426
427         for (i=1 ; i<nummodels ; i++)
428         {
429                 isworldmodel = i == 1; // LordHavoc: first model is the world model
430                 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
431                 if (cl.model_precache[i] == NULL)
432                 {
433                         Con_Printf("Model %s not found\n", model_precache[i]);
434                         return;
435                 }
436                 CL_KeepaliveMessage ();
437         }
438
439         S_BeginPrecaching ();
440         for (i=1 ; i<numsounds ; i++)
441         {
442                 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
443                 CL_KeepaliveMessage ();
444         }
445         S_EndPrecaching ();
446
447
448 // local state
449         cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
450         
451         R_NewMap ();
452
453         Hunk_Check ();          // make sure nothing is hurt
454         
455         noclip_anglehack = false;               // noclip is turned off at start        
456 }
457
458 void CL_ValidateState(entity_state_t *s)
459 {
460         model_t *model;
461
462         if (!s->active)
463                 return;
464
465         if (s->modelindex >= MAX_MODELS)
466                 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
467
468         // colormap is client index + 1
469         if (s->colormap > cl.maxclients)
470                 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
471
472         model = cl.model_precache[s->modelindex];
473         if (model && s->frame >= model->numframes)
474         {
475                 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
476                 s->frame = 0;
477         }
478 }
479
480 /*
481 ==================
482 CL_ParseUpdate
483
484 Parse an entity update message from the server
485 If an entities model or origin changes from frame to frame, it must be
486 relinked.  Other attributes can change without relinking.
487 ==================
488 */
489 byte entkill[MAX_EDICTS];
490 void CL_ParseUpdate (int bits)
491 {
492         int num, deltadie;
493         entity_t *ent;
494
495         if (cls.signon == SIGNONS - 1)
496         {       // first update is the final signon stage
497                 cls.signon = SIGNONS;
498                 CL_SignonReply ();
499         }
500
501         if (bits & U_MOREBITS)
502                 bits |= (MSG_ReadByte()<<8);
503         if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
504         {
505                 bits |= MSG_ReadByte() << 16;
506                 if (bits & U_EXTEND2)
507                         bits |= MSG_ReadByte() << 24;
508         }
509
510         if (bits & U_LONGENTITY)        
511                 num = (unsigned) MSG_ReadShort ();
512         else
513                 num = (unsigned) MSG_ReadByte ();
514
515         if (num >= MAX_EDICTS)
516                 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
517         if (num < 1)
518                 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
519
520         // mark as visible (no kill)
521         entkill[num] = 0;
522
523         ent = CL_EntityNum (num);
524
525         ent->state_previous = ent->state_current;
526         deltadie = false;
527         if (bits & U_DELTA)
528         {
529                 if (!ent->state_current.active)
530                         deltadie = true; // was not present in previous frame, leave hidden until next full update
531         }
532         else
533                 ent->state_current = ent->state_baseline;
534
535         ent->state_current.time = cl.mtime[0];
536
537         ent->state_current.flags = 0;
538         ent->state_current.active = true;
539         if (bits & U_MODEL)             ent->state_current.modelindex = (ent->state_current.modelindex & 0xFF00) | MSG_ReadByte();
540         if (bits & U_FRAME)             ent->state_current.frame = (ent->state_current.frame & 0xFF00) | MSG_ReadByte();
541         if (bits & U_COLORMAP)  ent->state_current.colormap = MSG_ReadByte();
542         if (bits & U_SKIN)              ent->state_current.skin = MSG_ReadByte();
543         if (bits & U_EFFECTS)   ent->state_current.effects = (ent->state_current.effects & 0xFF00) | MSG_ReadByte();
544         if (bits & U_ORIGIN1)   ent->state_current.origin[0] = MSG_ReadCoord();
545         if (bits & U_ANGLE1)    ent->state_current.angles[0] = MSG_ReadAngle();
546         if (bits & U_ORIGIN2)   ent->state_current.origin[1] = MSG_ReadCoord();
547         if (bits & U_ANGLE2)    ent->state_current.angles[1] = MSG_ReadAngle();
548         if (bits & U_ORIGIN3)   ent->state_current.origin[2] = MSG_ReadCoord();
549         if (bits & U_ANGLE3)    ent->state_current.angles[2] = MSG_ReadAngle();
550         if (bits & U_STEP)              ent->state_current.flags |= RENDER_STEP;
551         if (bits & U_ALPHA)             ent->state_current.alpha = MSG_ReadByte();
552         if (bits & U_SCALE)             ent->state_current.scale = MSG_ReadByte();
553         if (bits & U_EFFECTS2)  ent->state_current.effects = (ent->state_current.effects & 0x00FF) | (MSG_ReadByte() << 8);
554         if (bits & U_GLOWSIZE)  ent->state_current.glowsize = MSG_ReadByte();
555         if (bits & U_GLOWCOLOR) ent->state_current.glowcolor = MSG_ReadByte();
556         if (bits & U_GLOWTRAIL) ent->state_current.flags |= RENDER_GLOWTRAIL;
557         if (bits & U_COLORMOD)  ent->state_current.colormod = MSG_ReadByte();
558         if (bits & U_FRAME2)    ent->state_current.frame = (ent->state_current.frame & 0x00FF) | (MSG_ReadByte() << 8);
559         if (bits & U_MODEL2)    ent->state_current.modelindex = (ent->state_current.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
560         if (bits & U_VIEWMODEL) ent->state_current.flags |= RENDER_VIEWMODEL;
561
562         // LordHavoc: to allow playback of the Nehahra movie
563         if (Nehahrademcompatibility && (bits & U_EXTEND1))
564         {
565                 // LordHavoc: evil format
566                 int i = MSG_ReadFloat();
567                 int j = MSG_ReadFloat() * 255.0f;
568                 if (i == 2)
569                 {
570                         if (MSG_ReadFloat())
571                                 ent->state_current.effects |= EF_FULLBRIGHT;
572                 }
573                 if (j < 0)
574                         ent->state_current.alpha = 0;
575                 else if (j == 0 || j >= 255)
576                         ent->state_current.alpha = 255;
577                 else
578                         ent->state_current.alpha = j;
579         }
580
581         if (deltadie)
582         {
583                 // hide the entity
584                 ent->state_current.active = false;
585         }
586         else
587         {
588                 CL_ValidateState(&ent->state_current);
589
590                 /*
591                 if (!ent->state_current.active)
592                 {
593                         if (bits & U_DELTA)
594                         {
595                                 if (bits & U_MODEL)
596                                         Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i %i\n", num, ent->state_previous.modelindex, ent->state_current.modelindex);
597                                 else
598                                         Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i\n", num, ent->state_previous.modelindex);
599                         }
600                         else
601                         {
602                                 if (bits & U_MODEL)
603                                         Con_Printf("CL_ParseUpdate:       NULL model on %i: %i %i\n", num, ent->state_baseline.modelindex, ent->state_current.modelindex);
604                                 else
605                                         Con_Printf("CL_ParseUpdate:       NULL model on %i: %i\n", num, ent->state_baseline.modelindex);
606                         }
607                 }
608                 */
609         }
610 }
611
612 int entityupdatestart;
613 void CL_EntityUpdateBegin(int start)
614 {
615         if (start < 0 || start >= MAX_EDICTS)
616                 Host_Error("CL_EntityUpdateBegin: start (%i) < 0 or >= MAX_EDICTS (%i)\n", start, MAX_EDICTS);
617         entityupdatestart = start;
618         memset(entkill, 1, MAX_EDICTS);
619 }
620
621 void CL_EntityUpdateEnd(int end)
622 {
623         int i;
624         if (end < 0 || end > MAX_EDICTS)
625                 Host_Error("CL_EntityUpdateEnd: end (%i) < 0 or > MAX_EDICTS (%i)\n", end, MAX_EDICTS);
626         for (i = entityupdatestart;i < end;i++)
627                 if (entkill[i])
628                         cl_entities[i].state_current.active = 0;
629 }
630
631 /*
632 ==================
633 CL_ParseBaseline
634 ==================
635 */
636 void CL_ParseBaseline (entity_t *ent, int largemodelindex)
637 {
638         int i;
639
640         memset(&ent->state_baseline, 0, sizeof(entity_state_t));
641         ent->state_baseline.active = true;
642         if (largemodelindex)
643                 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
644         else
645                 ent->state_baseline.modelindex = MSG_ReadByte ();
646         ent->state_baseline.frame = MSG_ReadByte ();
647         ent->state_baseline.colormap = MSG_ReadByte();
648         ent->state_baseline.skin = MSG_ReadByte();
649         for (i = 0;i < 3;i++)
650         {
651                 ent->state_baseline.origin[i] = MSG_ReadCoord ();
652                 ent->state_baseline.angles[i] = MSG_ReadAngle ();
653         }
654         ent->state_baseline.alpha = 255;
655         ent->state_baseline.scale = 16;
656         ent->state_baseline.glowsize = 0;
657         ent->state_baseline.glowcolor = 254;
658         ent->state_baseline.colormod = 255;
659         ent->state_previous = ent->state_current = ent->state_baseline;
660
661         CL_ValidateState(&ent->state_baseline);
662 }
663
664
665 /*
666 ==================
667 CL_ParseClientdata
668
669 Server information pertaining to this client only
670 ==================
671 */
672 void CL_ParseClientdata (int bits)
673 {
674         int i, j;
675
676         bits &= 0xFFFF;
677         if (bits & SU_EXTEND1)
678                 bits |= (MSG_ReadByte() << 16);
679         if (bits & SU_EXTEND2)
680                 bits |= (MSG_ReadByte() << 24);
681
682         if (bits & SU_VIEWHEIGHT)
683                 cl.viewheight = MSG_ReadChar ();
684         else
685                 cl.viewheight = DEFAULT_VIEWHEIGHT;
686
687         if (bits & SU_IDEALPITCH)
688                 cl.idealpitch = MSG_ReadChar ();
689         else
690                 cl.idealpitch = 0;
691         
692         VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
693         for (i=0 ; i<3 ; i++)
694         {
695                 if (bits & (SU_PUNCH1<<i) )
696                 {
697                         if (dpprotocol)
698                                 cl.punchangle[i] = MSG_ReadPreciseAngle();
699                         else
700                                 cl.punchangle[i] = MSG_ReadChar();
701                 }
702                 else
703                         cl.punchangle[i] = 0;
704                 if (bits & (SU_PUNCHVEC1<<i))
705                         cl.punchvector[i] = MSG_ReadFloatCoord();
706                 else
707                         cl.punchvector[i] = 0;
708                 if (bits & (SU_VELOCITY1<<i) )
709                         cl.mvelocity[0][i] = MSG_ReadChar()*16;
710                 else
711                         cl.mvelocity[0][i] = 0;
712         }
713
714         i = MSG_ReadLong ();
715         if (cl.items != i)
716         {       // set flash times
717                 for (j=0 ; j<32 ; j++)
718                         if ( (i & (1<<j)) && !(cl.items & (1<<j)))
719                                 cl.item_gettime[j] = cl.time;
720                 cl.items = i;
721         }
722                 
723         cl.onground = (bits & SU_ONGROUND) != 0;
724         cl.inwater = (bits & SU_INWATER) != 0;
725
726         cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
727         cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
728         cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
729         cl.stats[STAT_HEALTH] = MSG_ReadShort();
730         cl.stats[STAT_AMMO] = MSG_ReadByte();
731
732         cl.stats[STAT_SHELLS] = MSG_ReadByte();
733         cl.stats[STAT_NAILS] = MSG_ReadByte();
734         cl.stats[STAT_ROCKETS] = MSG_ReadByte();
735         cl.stats[STAT_CELLS] = MSG_ReadByte();
736
737         i = MSG_ReadByte ();
738
739         if (standard_quake)
740                 cl.stats[STAT_ACTIVEWEAPON] = i;
741         else
742                 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
743 }
744
745 /*
746 =====================
747 CL_ParseStatic
748 =====================
749 */
750 void CL_ParseStatic (int largemodelindex)
751 {
752         entity_t *ent;
753                 
754         if (cl.num_statics >= MAX_STATIC_ENTITIES)
755                 Host_Error ("Too many static entities");
756         ent = &cl_static_entities[cl.num_statics++];
757         CL_ParseBaseline (ent, largemodelindex);
758
759 // copy it to the current state
760         ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
761         ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
762         ent->render.framelerp = 0;
763         ent->render.lerp_starttime = -1;
764         // make torchs play out of sync
765         ent->render.frame1start = ent->render.frame2start = -(rand() & 32767);
766         ent->render.colormap = -1; // no special coloring
767         ent->render.skinnum = ent->state_baseline.skin;
768         ent->render.effects = ent->state_baseline.effects;
769         ent->render.alpha = 1;
770         ent->render.scale = 1;
771         ent->render.alpha = 1;
772         ent->render.glowsize = 0;
773         ent->render.glowcolor = 254;
774         ent->render.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
775
776         VectorCopy (ent->state_baseline.origin, ent->render.origin);
777         VectorCopy (ent->state_baseline.angles, ent->render.angles);    
778 //      R_AddEfrags (ent);
779 }
780
781 /*
782 ===================
783 CL_ParseStaticSound
784 ===================
785 */
786 void CL_ParseStaticSound (void)
787 {
788         vec3_t          org;
789         int                     sound_num, vol, atten;
790
791         MSG_ReadVector(org);
792         sound_num = MSG_ReadByte ();
793         vol = MSG_ReadByte ();
794         atten = MSG_ReadByte ();
795         
796         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
797 }
798
799 void CL_ParseEffect (void)
800 {
801         vec3_t          org;
802         int                     modelindex, startframe, framecount, framerate;
803
804         MSG_ReadVector(org);
805         modelindex = MSG_ReadByte ();
806         startframe = MSG_ReadByte ();
807         framecount = MSG_ReadByte ();
808         framerate = MSG_ReadByte ();
809
810         CL_Effect(org, modelindex, startframe, framecount, framerate);
811 }
812
813 void CL_ParseEffect2 (void)
814 {
815         vec3_t          org;
816         int                     modelindex, startframe, framecount, framerate;
817
818         MSG_ReadVector(org);
819         modelindex = MSG_ReadShort ();
820         startframe = MSG_ReadByte ();
821         framecount = MSG_ReadByte ();
822         framerate = MSG_ReadByte ();
823
824         CL_Effect(org, modelindex, startframe, framecount, framerate);
825 }
826
827
828 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
829
830 extern void SHOWLMP_decodehide();
831 extern void SHOWLMP_decodeshow();
832 extern void R_SetSkyBox(char* sky);
833 extern int netshown;
834
835 /*
836 =====================
837 CL_ParseServerMessage
838 =====================
839 */
840 void CL_ParseServerMessage (void)
841 {
842         int                     cmd;
843         int                     i, updateend;
844         byte            cmdlog[32];
845         char            *cmdlogname[32], *temp;
846         int                     cmdindex, cmdcount = 0;
847         
848 //
849 // if recording demos, copy the message out
850 //
851         if (cl_shownet.value == 1)
852         {
853                 Con_Printf ("%i ",net_message.cursize);
854                 netshown = true;
855         }
856         else if (cl_shownet.value == 2)
857         {
858                 Con_Printf ("------------------\n");
859                 netshown = true;
860         }
861         
862         cl.onground = false;    // unless the server says otherwise     
863 //
864 // parse the message
865 //
866         MSG_BeginReading ();
867
868         updateend = false;
869         
870         while (1)
871         {
872                 if (msg_badread)
873                         Host_Error ("CL_ParseServerMessage: Bad server message");
874
875                 cmd = MSG_ReadByte ();
876
877                 if (cmd == -1)
878                 {
879                         SHOWNET("END OF MESSAGE");
880                         break;          // end of message
881                 }
882
883                 cmdindex = cmdcount & 31;
884                 cmdcount++;
885                 cmdlog[cmdindex] = cmd;
886
887                 // if the high bit of the command byte is set, it is a fast update
888                 if (cmd & 128)
889                 {
890                         // 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)
891                         temp = "entity";
892                         cmdlogname[cmdindex] = temp;
893                         SHOWNET("fast update");
894                         CL_ParseUpdate (cmd&127);
895                         continue;
896                 }
897
898                 SHOWNET(svc_strings[cmd]);
899                 cmdlogname[cmdindex] = svc_strings[cmd];
900                 if (!cmdlogname[cmdindex])
901                 {
902                         // 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)
903                         temp = "<unknown>";
904                         cmdlogname[cmdindex] = temp;
905                 }
906         
907                 // other commands
908                 switch (cmd)
909                 {
910                 default:
911                         {
912                                 char description[32*64], temp[64];
913                                 int count;
914                                 strcpy(description, "packet dump: ");
915                                 i = cmdcount - 32;
916                                 if (i < 0)
917                                         i = 0;
918                                 count = cmdcount - i;
919                                 i &= 31;
920                                 while(count > 0)
921                                 {
922                                         sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
923                                         strcat(description, temp);
924                                         count--;
925                                         i++;
926                                         i &= 31;
927                                 }
928                                 description[strlen(description)-1] = '\n'; // replace the last space with a newline
929                                 Con_Printf(description);
930                                 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
931                         }
932                         break;
933                         
934                 case svc_nop:
935 //                      Con_Printf ("svc_nop\n");
936                         break;
937                         
938                 case svc_time:
939                         // handle old protocols which do not have entity update ranges
940                         CL_EntityUpdateBegin(0);
941                         updateend = true;
942                         cl.mtime[1] = cl.mtime[0];
943                         cl.mtime[0] = MSG_ReadFloat ();                 
944                         break;
945                         
946                 case svc_clientdata:
947                         i = MSG_ReadShort ();
948                         CL_ParseClientdata (i);
949                         break;
950                 
951                 case svc_version:
952                         i = MSG_ReadLong ();
953                         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
954                                 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
955                         Nehahrademcompatibility = false;
956                         if (i == 250)
957                                 Nehahrademcompatibility = true;
958                         if (cls.demoplayback && demo_nehahra.value)
959                                 Nehahrademcompatibility = true;
960                         dpprotocol = i == DPPROTOCOL_VERSION;
961                         break;
962                         
963                 case svc_disconnect:
964                         Host_EndGame ("Server disconnected\n");
965
966                 case svc_print:
967                         Con_Printf ("%s", MSG_ReadString ());
968                         break;
969                         
970                 case svc_centerprint:
971                         SCR_CenterPrint (MSG_ReadString ());
972                         break;
973                         
974                 case svc_stufftext:
975                         Cbuf_AddText (MSG_ReadString ());
976                         break;
977                         
978                 case svc_damage:
979                         V_ParseDamage ();
980                         break;
981                         
982                 case svc_serverinfo:
983                         CL_ParseServerInfo ();
984                         vid.recalc_refdef = true;       // leave intermission full screen
985                         break;
986                         
987                 case svc_setangle:
988                         for (i=0 ; i<3 ; i++)
989                                 cl.viewangles[i] = MSG_ReadAngle ();
990                         break;
991                         
992                 case svc_setview:
993                         cl.viewentity = MSG_ReadShort ();
994                         break;
995                                         
996                 case svc_lightstyle:
997                         i = MSG_ReadByte ();
998                         if (i >= MAX_LIGHTSTYLES)
999                                 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1000                         strncpy (cl_lightstyle[i].map,  MSG_ReadString(), MAX_STYLESTRING - 1);
1001                         cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1002                         cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1003                         break;
1004                         
1005                 case svc_sound:
1006                         CL_ParseStartSoundPacket(false);
1007                         break;
1008
1009                 case svc_sound2:
1010                         CL_ParseStartSoundPacket(true);
1011                         break;
1012
1013                 case svc_stopsound:
1014                         i = MSG_ReadShort();
1015                         S_StopSound(i>>3, i&7);
1016                         break;
1017                 
1018                 case svc_updatename:
1019                         i = MSG_ReadByte ();
1020                         if (i >= cl.maxclients)
1021                                 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1022                         strcpy (cl.scores[i].name, MSG_ReadString ());
1023                         break;
1024                         
1025                 case svc_updatefrags:
1026                         i = MSG_ReadByte ();
1027                         if (i >= cl.maxclients)
1028                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1029                         cl.scores[i].frags = MSG_ReadShort ();
1030                         break;                  
1031
1032                 case svc_updatecolors:
1033                         i = MSG_ReadByte ();
1034                         if (i >= cl.maxclients)
1035                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1036                         cl.scores[i].colors = MSG_ReadByte ();
1037                         break;
1038                         
1039                 case svc_particle:
1040                         R_ParseParticleEffect ();
1041                         break;
1042
1043                 case svc_effect:
1044                         CL_ParseEffect ();
1045                         break;
1046
1047                 case svc_effect2:
1048                         CL_ParseEffect2 ();
1049                         break;
1050
1051                 case svc_spawnbaseline:
1052                         i = MSG_ReadShort ();
1053                         // must use CL_EntityNum() to force cl.num_entities up
1054                         CL_ParseBaseline (CL_EntityNum(i), false);
1055                         break;
1056                 case svc_spawnbaseline2:
1057                         i = MSG_ReadShort ();
1058                         // must use CL_EntityNum() to force cl.num_entities up
1059                         CL_ParseBaseline (CL_EntityNum(i), false);
1060                         break;
1061                 case svc_spawnstatic:
1062                         CL_ParseStatic (false);
1063                         break;
1064                 case svc_spawnstatic2:
1065                         CL_ParseStatic (true);
1066                         break;
1067                 case svc_temp_entity:
1068                         CL_ParseTEnt ();
1069                         break;
1070
1071                 case svc_setpause:
1072                         cl.paused = MSG_ReadByte ();
1073                         if (cl.paused)
1074                                 CDAudio_Pause ();
1075                         else
1076                                 CDAudio_Resume ();
1077                         break;
1078                         
1079                 case svc_signonnum:
1080                         i = MSG_ReadByte ();
1081                         if (i <= cls.signon)
1082                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
1083                         cls.signon = i;
1084                         CL_SignonReply ();
1085                         break;
1086
1087                 case svc_killedmonster:
1088                         cl.stats[STAT_MONSTERS]++;
1089                         break;
1090
1091                 case svc_foundsecret:
1092                         cl.stats[STAT_SECRETS]++;
1093                         break;
1094
1095                 case svc_updatestat:
1096                         i = MSG_ReadByte ();
1097                         if (i < 0 || i >= MAX_CL_STATS)
1098                                 Host_Error ("svc_updatestat: %i is invalid", i);
1099                         cl.stats[i] = MSG_ReadLong ();
1100                         break;
1101                         
1102                 case svc_spawnstaticsound:
1103                         CL_ParseStaticSound ();
1104                         break;
1105
1106                 case svc_cdtrack:
1107                         cl.cdtrack = MSG_ReadByte ();
1108                         cl.looptrack = MSG_ReadByte ();
1109                         if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1110                                 CDAudio_Play ((byte)cls.forcetrack, true);
1111                         else
1112                                 CDAudio_Play ((byte)cl.cdtrack, true);
1113                         break;
1114
1115                 case svc_intermission:
1116                         cl.intermission = 1;
1117                         cl.completed_time = cl.time;
1118                         vid.recalc_refdef = true;       // go to full screen
1119                         break;
1120
1121                 case svc_finale:
1122                         cl.intermission = 2;
1123                         cl.completed_time = cl.time;
1124                         vid.recalc_refdef = true;       // go to full screen
1125                         SCR_CenterPrint (MSG_ReadString ());                    
1126                         break;
1127
1128                 case svc_cutscene:
1129                         cl.intermission = 3;
1130                         cl.completed_time = cl.time;
1131                         vid.recalc_refdef = true;       // go to full screen
1132                         SCR_CenterPrint (MSG_ReadString ());                    
1133                         break;
1134
1135                 case svc_sellscreen:
1136                         Cmd_ExecuteString ("help", src_command);
1137                         break;
1138                 case svc_hidelmp:
1139                         SHOWLMP_decodehide();
1140                         break;
1141                 case svc_showlmp:
1142                         SHOWLMP_decodeshow();
1143                         break;
1144                 case svc_entitiesbegin:
1145                         // the beginning of an entity update range
1146                         CL_EntityUpdateBegin((unsigned) MSG_ReadShort());
1147                         break;
1148                 case svc_entitiesend:
1149                         // the end of an entity update range
1150                         CL_EntityUpdateEnd((unsigned) MSG_ReadShort());
1151                         updateend = false;
1152                         break;
1153                 }
1154         }
1155
1156         if (updateend)
1157                 CL_EntityUpdateEnd(MAX_EDICTS);
1158 }
1159