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