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