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