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