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