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