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