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