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