]> icculus.org git repositories - divverent/darkplaces.git/blob - cl_parse.c
-lXIE does not seem to be necessary, disabled (but left a comment incase anyone needs it)
[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         sizebuf_t       old;
201         qbyte           olddata[8192];
202         
203         if (sv.active)
204                 return;         // no need if server is local
205         if (cls.demoplayback)
206                 return;
207
208 // read messages from server, should just be nops
209         old = net_message;
210         memcpy (olddata, net_message.data, net_message.cursize);
211         
212         do
213         {
214                 ret = CL_GetMessage ();
215                 switch (ret)
216                 {
217                 default:
218                         Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");               
219                 case 0:
220                         break;  // nothing waiting
221                 case 1:
222                         Host_Error ("CL_KeepaliveMessage: received a message");
223                         break;
224                 case 2:
225                         if (MSG_ReadByte() != svc_nop)
226                                 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
227                         break;
228                 }
229         } while (ret);
230
231         net_message = old;
232         memcpy (net_message.data, olddata, net_message.cursize);
233
234 // check time
235         time = Sys_DoubleTime ();
236         if (time - lastmsg < 5)
237                 return;
238         lastmsg = time;
239
240 // write out a nop
241         Con_Printf ("--> client to server keepalive\n");
242
243         MSG_WriteByte (&cls.message, clc_nop);
244         NET_SendMessage (cls.netcon, &cls.message);
245         SZ_Clear (&cls.message);
246 }
247
248 void CL_ParseEntityLump(char *entdata)
249 {
250         char *data;
251         char key[128], value[4096];
252         FOG_clear(); // LordHavoc: no fog until set
253         R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
254         data = entdata;
255         if (!data)
256                 return;
257         data = COM_Parse(data);
258         if (!data)
259                 return; // error
260         if (com_token[0] != '{')
261                 return; // error
262         while (1)
263         {
264                 data = COM_Parse(data);
265                 if (!data)
266                         return; // error
267                 if (com_token[0] == '}')
268                         break; // end of worldspawn
269                 if (com_token[0] == '_')
270                         strcpy(key, com_token + 1);
271                 else
272                         strcpy(key, com_token);
273                 while (key[strlen(key)-1] == ' ') // remove trailing spaces
274                         key[strlen(key)-1] = 0;
275                 data = COM_Parse(data);
276                 if (!data)
277                         return; // error
278                 strcpy(value, com_token);
279                 if (!strcmp("sky", key))
280                         R_SetSkyBox(value);
281                 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
282                         R_SetSkyBox(value);
283                 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
284                         R_SetSkyBox(value);
285                 else if (!strcmp("fog", key))
286                         sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
287                 else if (!strcmp("fog_density", key))
288                         fog_density = atof(value);
289                 else if (!strcmp("fog_red", key))
290                         fog_red = atof(value);
291                 else if (!strcmp("fog_green", key))
292                         fog_green = atof(value);
293                 else if (!strcmp("fog_blue", key))
294                         fog_blue = atof(value);
295         }
296 }
297
298 /*
299 =====================
300 CL_SignonReply
301
302 An svc_signonnum has been received, perform a client side setup
303 =====================
304 */
305 static void CL_SignonReply (void)
306 {
307         char    str[8192];
308
309 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
310
311         switch (cls.signon)
312         {
313         case 1:
314                 MSG_WriteByte (&cls.message, clc_stringcmd);
315                 MSG_WriteString (&cls.message, "prespawn");
316                 break;
317
318         case 2:
319                 MSG_WriteByte (&cls.message, clc_stringcmd);
320                 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
321
322                 MSG_WriteByte (&cls.message, clc_stringcmd);
323                 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
324
325                 if (cl_pmodel.integer)
326                 {
327                         MSG_WriteByte (&cls.message, clc_stringcmd);
328                         MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
329                 }
330
331                 MSG_WriteByte (&cls.message, clc_stringcmd);
332                 sprintf (str, "spawn %s", cls.spawnparms);
333                 MSG_WriteString (&cls.message, str);
334                 break;
335
336         case 3:
337                 MSG_WriteByte (&cls.message, clc_stringcmd);
338                 MSG_WriteString (&cls.message, "begin");
339                 break;
340
341         case 4:
342                 SCR_EndLoadingPlaque ();                // allow normal screen updates
343                 Con_ClearNotify();
344                 break;
345         }
346 }
347
348 /*
349 ==================
350 CL_ParseServerInfo
351 ==================
352 */
353 void CL_ParseServerInfo (void)
354 {
355         char    *str;
356         int             i;
357         int             nummodels, numsounds;
358         char    model_precache[MAX_MODELS][MAX_QPATH];
359         char    sound_precache[MAX_SOUNDS][MAX_QPATH];
360
361         Con_DPrintf ("Serverinfo packet received.\n");
362 //
363 // wipe the client_state_t struct
364 //
365         CL_ClearState ();
366
367 // parse protocol version number
368         i = MSG_ReadLong ();
369         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
370         {
371                 Con_Printf ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
372                 return;
373         }
374         Nehahrademcompatibility = false;
375         if (i == 250)
376                 Nehahrademcompatibility = true;
377         if (cls.demoplayback && demo_nehahra.integer)
378                 Nehahrademcompatibility = true;
379         dpprotocol = i;
380         if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
381                 dpprotocol = 0;
382
383 // parse maxclients
384         cl.maxclients = MSG_ReadByte ();
385         if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
386         {
387                 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
388                 return;
389         }
390         cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
391
392 // parse gametype
393         cl.gametype = MSG_ReadByte ();
394
395 // parse signon message
396         str = MSG_ReadString ();
397         strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
398
399 // seperate the printfs so the server message can have a color
400         if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
401         {
402                 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");
403                 Con_Printf ("%c%s\n", 2, str);
404         }
405
406 //
407 // first we go through and touch all of the precache data that still
408 // happens to be in the cache, so precaching something else doesn't
409 // needlessly purge it
410 //
411
412         Mem_CheckSentinelsGlobal();
413
414         Mod_ClearUsed();
415
416 // precache models
417         memset (cl.model_precache, 0, sizeof(cl.model_precache));
418         for (nummodels=1 ; ; nummodels++)
419         {
420                 str = MSG_ReadString ();
421                 if (!str[0])
422                         break;
423                 if (nummodels==MAX_MODELS)
424                 {
425                         Host_Error ("Server sent too many model precaches\n");
426                         return;
427                 }
428                 if (strlen(str) >= MAX_QPATH)
429                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
430                 strcpy (model_precache[nummodels], str);
431                 Mod_TouchModel (str);
432         }
433
434 // precache sounds
435         memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
436         for (numsounds=1 ; ; numsounds++)
437         {
438                 str = MSG_ReadString ();
439                 if (!str[0])
440                         break;
441                 if (numsounds==MAX_SOUNDS)
442                 {
443                         Host_Error ("Server sent too many sound precaches\n");
444                         return;
445                 }
446                 if (strlen(str) >= MAX_QPATH)
447                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
448                 strcpy (sound_precache[numsounds], str);
449                 S_TouchSound (str);
450         }
451
452         Mod_PurgeUnused();
453
454 //
455 // now we try to load everything else until a cache allocation fails
456 //
457
458         for (i=1 ; i<nummodels ; i++)
459         {
460                 // LordHavoc: i == 1 means the first model is the world model
461                 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
462
463                 if (cl.model_precache[i] == NULL)
464                 {
465                         Host_Error("Model %s not found\n", model_precache[i]);
466                         return;
467                 }
468                 CL_KeepaliveMessage ();
469         }
470
471         S_BeginPrecaching ();
472         for (i=1 ; i<numsounds ; i++)
473         {
474                 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
475                 CL_KeepaliveMessage ();
476         }
477         S_EndPrecaching ();
478
479 // local state
480         cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
481         cl_entities[0].render.scale = 1;
482         cl_entities[0].render.alpha = 1;
483
484         R_NewMap ();
485
486         CL_CGVM_Start();
487
488         Mem_CheckSentinelsGlobal();
489
490         noclip_anglehack = false;               // noclip is turned off at start
491 }
492
493 void CL_ValidateState(entity_state_t *s)
494 {
495         model_t *model;
496
497         if (!s->active)
498                 return;
499
500         if (s->modelindex >= MAX_MODELS)
501                 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
502
503         // colormap is client index + 1
504         if (s->colormap > cl.maxclients)
505                 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
506
507         model = cl.model_precache[s->modelindex];
508         Mod_CheckLoaded(model);
509         if (model && s->frame >= model->numframes)
510         {
511                 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
512                 s->frame = 0;
513         }
514         if (model && s->skin > 0 && s->skin >= model->numskins)
515         {
516                 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
517                 s->skin = 0;
518         }
519 }
520
521 /*
522 ==================
523 CL_ParseUpdate
524
525 Parse an entity update message from the server
526 If an entities model or origin changes from frame to frame, it must be
527 relinked.  Other attributes can change without relinking.
528 ==================
529 */
530 qbyte 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         cl.viewzoomold = cl.viewzoomnew; // for interpolation
861         if (bits & SU_VIEWZOOM)
862         {
863                 i = MSG_ReadByte();
864                 if (i < 2)
865                         i = 2;
866                 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
867         }
868         else
869                 cl.viewzoomnew = 1;
870
871 }
872
873 /*
874 =====================
875 CL_ParseStatic
876 =====================
877 */
878 void CL_ParseStatic (int large)
879 {
880         entity_t *ent;
881
882         if (cl.num_statics >= MAX_STATIC_ENTITIES)
883                 Host_Error ("Too many static entities");
884         ent = &cl_static_entities[cl.num_statics++];
885         CL_ParseBaseline (ent, large);
886
887 // copy it to the current state
888         ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
889         ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
890         ent->render.framelerp = 0;
891         // make torchs play out of sync
892         ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
893         ent->render.colormap = -1; // no special coloring
894         ent->render.skinnum = ent->state_baseline.skin;
895         ent->render.effects = ent->state_baseline.effects;
896         ent->render.alpha = 1;
897         ent->render.scale = 1;
898         ent->render.alpha = 1;
899
900         VectorCopy (ent->state_baseline.origin, ent->render.origin);
901         VectorCopy (ent->state_baseline.angles, ent->render.angles);    
902 }
903
904 /*
905 ===================
906 CL_ParseStaticSound
907 ===================
908 */
909 void CL_ParseStaticSound (int large)
910 {
911         vec3_t          org;
912         int                     sound_num, vol, atten;
913
914         MSG_ReadVector(org);
915         if (large)
916                 sound_num = (unsigned short) MSG_ReadShort ();
917         else
918                 sound_num = MSG_ReadByte ();
919         vol = MSG_ReadByte ();
920         atten = MSG_ReadByte ();
921
922         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
923 }
924
925 void CL_ParseEffect (void)
926 {
927         vec3_t          org;
928         int                     modelindex, startframe, framecount, framerate;
929
930         MSG_ReadVector(org);
931         modelindex = MSG_ReadByte ();
932         startframe = MSG_ReadByte ();
933         framecount = MSG_ReadByte ();
934         framerate = MSG_ReadByte ();
935
936         CL_Effect(org, modelindex, startframe, framecount, framerate);
937 }
938
939 void CL_ParseEffect2 (void)
940 {
941         vec3_t          org;
942         int                     modelindex, startframe, framecount, framerate;
943
944         MSG_ReadVector(org);
945         modelindex = MSG_ReadShort ();
946         startframe = MSG_ReadShort ();
947         framecount = MSG_ReadByte ();
948         framerate = MSG_ReadByte ();
949
950         CL_Effect(org, modelindex, startframe, framecount, framerate);
951 }
952
953
954 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
955
956 static qbyte cgamenetbuffer[65536];
957
958 /*
959 =====================
960 CL_ParseServerMessage
961 =====================
962 */
963 void CL_ParseServerMessage (void)
964 {
965         int                     cmd;
966         int                     i, entitiesupdated;
967         qbyte           cmdlog[32];
968         char            *cmdlogname[32], *temp;
969         int                     cmdindex, cmdcount = 0;
970
971 //
972 // if recording demos, copy the message out
973 //
974         if (cl_shownet.integer == 1)
975                 Con_Printf ("%i ",net_message.cursize);
976         else if (cl_shownet.integer == 2)
977                 Con_Printf ("------------------\n");
978
979         cl.onground = false;    // unless the server says otherwise
980 //
981 // parse the message
982 //
983         MSG_BeginReading ();
984
985         entitiesupdated = false;
986         CL_EntityUpdateSetup();
987
988         while (1)
989         {
990                 if (msg_badread)
991                         Host_Error ("CL_ParseServerMessage: Bad server message");
992
993                 cmd = MSG_ReadByte ();
994
995                 if (cmd == -1)
996                 {
997                         SHOWNET("END OF MESSAGE");
998                         break;          // end of message
999                 }
1000
1001                 cmdindex = cmdcount & 31;
1002                 cmdcount++;
1003                 cmdlog[cmdindex] = cmd;
1004
1005                 // if the high bit of the command byte is set, it is a fast update
1006                 if (cmd & 128)
1007                 {
1008                         // 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)
1009                         temp = "entity";
1010                         cmdlogname[cmdindex] = temp;
1011                         SHOWNET("fast update");
1012                         if (cls.signon == SIGNONS - 1)
1013                         {       // first update is the final signon stage
1014                                 cls.signon = SIGNONS;
1015                                 CL_SignonReply ();
1016                         }
1017                         CL_ParseUpdate (cmd&127);
1018                         continue;
1019                 }
1020
1021                 SHOWNET(svc_strings[cmd]);
1022                 cmdlogname[cmdindex] = svc_strings[cmd];
1023                 if (!cmdlogname[cmdindex])
1024                 {
1025                         // LordHavoc: fix for bizarre problem in MSVC that I do not understand (if I assign the string pointer directly it ends up storing a NULL pointer)
1026                         temp = "<unknown>";
1027                         cmdlogname[cmdindex] = temp;
1028                 }
1029
1030                 // other commands
1031                 switch (cmd)
1032                 {
1033                 default:
1034                         {
1035                                 char description[32*64], temp[64];
1036                                 int count;
1037                                 strcpy(description, "packet dump: ");
1038                                 i = cmdcount - 32;
1039                                 if (i < 0)
1040                                         i = 0;
1041                                 count = cmdcount - i;
1042                                 i &= 31;
1043                                 while(count > 0)
1044                                 {
1045                                         sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1046                                         strcat(description, temp);
1047                                         count--;
1048                                         i++;
1049                                         i &= 31;
1050                                 }
1051                                 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1052                                 Con_Printf("%s", description);
1053                                 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1054                         }
1055                         break;
1056
1057                 case svc_nop:
1058 //                      Con_Printf ("svc_nop\n");
1059                         break;
1060
1061                 case svc_time:
1062                         // handle old protocols which do not have entity update ranges
1063                         entitiesupdated = true;
1064                         cl.mtime[1] = cl.mtime[0];
1065                         cl.mtime[0] = MSG_ReadFloat ();
1066                         break;
1067
1068                 case svc_clientdata:
1069                         i = MSG_ReadShort ();
1070                         CL_ParseClientdata (i);
1071                         break;
1072
1073                 case svc_version:
1074                         i = MSG_ReadLong ();
1075                         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1076                                 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1077                         Nehahrademcompatibility = false;
1078                         if (i == 250)
1079                                 Nehahrademcompatibility = true;
1080                         if (cls.demoplayback && demo_nehahra.integer)
1081                                 Nehahrademcompatibility = true;
1082                         dpprotocol = i;
1083                         if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1084                                 dpprotocol = 0;
1085                         break;
1086
1087                 case svc_disconnect:
1088                         Host_EndGame ("Server disconnected\n");
1089
1090                 case svc_print:
1091                         Con_Printf ("%s", MSG_ReadString ());
1092                         break;
1093
1094                 case svc_centerprint:
1095                         SCR_CenterPrint (MSG_ReadString ());
1096                         break;
1097
1098                 case svc_stufftext:
1099                         Cbuf_AddText (MSG_ReadString ());
1100                         break;
1101
1102                 case svc_damage:
1103                         V_ParseDamage ();
1104                         break;
1105
1106                 case svc_serverinfo:
1107                         CL_ParseServerInfo ();
1108 //                      vid.recalc_refdef = true;       // leave intermission full screen
1109                         break;
1110
1111                 case svc_setangle:
1112                         for (i=0 ; i<3 ; i++)
1113                                 cl.viewangles[i] = MSG_ReadAngle ();
1114                         break;
1115
1116                 case svc_setview:
1117                         cl.viewentity = MSG_ReadShort ();
1118                         break;
1119
1120                 case svc_lightstyle:
1121                         i = MSG_ReadByte ();
1122                         if (i >= MAX_LIGHTSTYLES)
1123                                 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1124                         strncpy (cl_lightstyle[i].map,  MSG_ReadString(), MAX_STYLESTRING - 1);
1125                         cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1126                         cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1127                         break;
1128
1129                 case svc_sound:
1130                         CL_ParseStartSoundPacket(false);
1131                         break;
1132
1133                 case svc_sound2:
1134                         CL_ParseStartSoundPacket(true);
1135                         break;
1136
1137                 case svc_stopsound:
1138                         i = MSG_ReadShort();
1139                         S_StopSound(i>>3, i&7);
1140                         break;
1141
1142                 case svc_updatename:
1143                         i = MSG_ReadByte ();
1144                         if (i >= cl.maxclients)
1145                                 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1146                         strcpy (cl.scores[i].name, MSG_ReadString ());
1147                         break;
1148
1149                 case svc_updatefrags:
1150                         i = MSG_ReadByte ();
1151                         if (i >= cl.maxclients)
1152                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1153                         cl.scores[i].frags = MSG_ReadShort ();
1154                         break;
1155
1156                 case svc_updatecolors:
1157                         i = MSG_ReadByte ();
1158                         if (i >= cl.maxclients)
1159                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1160                         cl.scores[i].colors = MSG_ReadByte ();
1161                         break;
1162
1163                 case svc_particle:
1164                         CL_ParseParticleEffect ();
1165                         break;
1166
1167                 case svc_effect:
1168                         CL_ParseEffect ();
1169                         break;
1170
1171                 case svc_effect2:
1172                         CL_ParseEffect2 ();
1173                         break;
1174
1175                 case svc_spawnbaseline:
1176                         i = MSG_ReadShort ();
1177                         // must use CL_EntityNum() to force cl.num_entities up
1178                         CL_ParseBaseline (CL_EntityNum(i), false);
1179                         break;
1180                 case svc_spawnbaseline2:
1181                         i = MSG_ReadShort ();
1182                         // must use CL_EntityNum() to force cl.num_entities up
1183                         CL_ParseBaseline (CL_EntityNum(i), true);
1184                         break;
1185                 case svc_spawnstatic:
1186                         CL_ParseStatic (false);
1187                         break;
1188                 case svc_spawnstatic2:
1189                         CL_ParseStatic (true);
1190                         break;
1191                 case svc_temp_entity:
1192                         CL_ParseTEnt ();
1193                         break;
1194
1195                 case svc_setpause:
1196                         cl.paused = MSG_ReadByte ();
1197                         if (cl.paused)
1198                                 CDAudio_Pause ();
1199                         else
1200                                 CDAudio_Resume ();
1201                         break;
1202
1203                 case svc_signonnum:
1204                         i = MSG_ReadByte ();
1205                         if (i <= cls.signon)
1206                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
1207                         cls.signon = i;
1208                         CL_SignonReply ();
1209                         break;
1210
1211                 case svc_killedmonster:
1212                         cl.stats[STAT_MONSTERS]++;
1213                         break;
1214
1215                 case svc_foundsecret:
1216                         cl.stats[STAT_SECRETS]++;
1217                         break;
1218
1219                 case svc_updatestat:
1220                         i = MSG_ReadByte ();
1221                         if (i < 0 || i >= MAX_CL_STATS)
1222                                 Host_Error ("svc_updatestat: %i is invalid", i);
1223                         cl.stats[i] = MSG_ReadLong ();
1224                         break;
1225
1226                 case svc_spawnstaticsound:
1227                         CL_ParseStaticSound (false);
1228                         break;
1229
1230                 case svc_spawnstaticsound2:
1231                         CL_ParseStaticSound (true);
1232                         break;
1233
1234                 case svc_cdtrack:
1235                         cl.cdtrack = MSG_ReadByte ();
1236                         cl.looptrack = MSG_ReadByte ();
1237                         if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1238                                 CDAudio_Play ((qbyte)cls.forcetrack, true);
1239                         else
1240                                 CDAudio_Play ((qbyte)cl.cdtrack, true);
1241                         break;
1242
1243                 case svc_intermission:
1244                         cl.intermission = 1;
1245                         cl.completed_time = cl.time;
1246 //                      vid.recalc_refdef = true;       // go to full screen
1247                         break;
1248
1249                 case svc_finale:
1250                         cl.intermission = 2;
1251                         cl.completed_time = cl.time;
1252 //                      vid.recalc_refdef = true;       // go to full screen
1253                         SCR_CenterPrint (MSG_ReadString ());
1254                         break;
1255
1256                 case svc_cutscene:
1257                         cl.intermission = 3;
1258                         cl.completed_time = cl.time;
1259 //                      vid.recalc_refdef = true;       // go to full screen
1260                         SCR_CenterPrint (MSG_ReadString ());
1261                         break;
1262
1263                 case svc_sellscreen:
1264                         Cmd_ExecuteString ("help", src_command);
1265                         break;
1266                 case svc_hidelmp:
1267                         SHOWLMP_decodehide();
1268                         break;
1269                 case svc_showlmp:
1270                         SHOWLMP_decodeshow();
1271                         break;
1272                 case svc_skybox:
1273                         R_SetSkyBox(MSG_ReadString());
1274                         break;
1275                 case svc_cgame:
1276                         {
1277                                 int length;
1278                                 length = (int) ((unsigned short) MSG_ReadShort());
1279                                 /*
1280                                 if (cgamenetbuffersize < length)
1281                                 {
1282                                         cgamenetbuffersize = length;
1283                                         if (cgamenetbuffer)
1284                                                 Mem_Free(cgamenetbuffer);
1285                                         cgamenetbuffer = Mem_Alloc(cgamenetbuffersize);
1286                                 }
1287                                 */
1288                                 for (i = 0;i < length;i++)
1289                                         cgamenetbuffer[i] = MSG_ReadByte();
1290                                 if (!msg_badread)
1291                                         CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1292                         }
1293                         break;
1294                 case svc_entities:
1295                         if (cls.signon == SIGNONS - 1)
1296                         {       // first update is the final signon stage
1297                                 cls.signon = SIGNONS;
1298                                 CL_SignonReply ();
1299                         }
1300                         CL_ReadEntityFrame();
1301                         break;
1302                 }
1303         }
1304
1305         if (entitiesupdated)
1306                 CL_EntityUpdateEnd();
1307 }