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