a big change with a little description...
[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         "", // 37
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         "", // 50
84         "svc_fog", // 51
85         "svc_effect", // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
86         "svc_effect2", // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate
87 };
88
89 //=============================================================================
90
91 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
92 qboolean dpprotocol; // LordHavoc: whether or not the current network stream is the enhanced DarkPlaces protocol
93
94 /*
95 ===============
96 CL_EntityNum
97
98 This error checks and tracks the total number of entities
99 ===============
100 */
101 entity_t        *CL_EntityNum (int num)
102 {
103         /*
104         if (num >= cl.num_entities)
105         {
106                 if (num >= MAX_EDICTS)
107                         Host_Error ("CL_EntityNum: %i is an invalid number",num);
108                 cl.num_entities = num;
109 //              while (cl.num_entities <= num)
110 //              {
111 //                      cl_entities[cl.num_entities].colormap = -1; // no special coloring
112 //                      cl.num_entities++;
113 //              }
114         }
115         */
116         if (num >= MAX_EDICTS)
117                 Host_Error ("CL_EntityNum: %i is an invalid number",num);
118                 
119         return &cl_entities[num];
120 }
121
122
123 /*
124 ==================
125 CL_ParseStartSoundPacket
126 ==================
127 */
128 void CL_ParseStartSoundPacket(int largesoundindex)
129 {
130     vec3_t  pos;
131     int         channel, ent;
132     int         sound_num;
133     int         volume;
134     int         field_mask;
135     float       attenuation;
136         int             i;
137                    
138     field_mask = MSG_ReadByte(); 
139
140     if (field_mask & SND_VOLUME)
141                 volume = MSG_ReadByte ();
142         else
143                 volume = DEFAULT_SOUND_PACKET_VOLUME;
144         
145     if (field_mask & SND_ATTENUATION)
146                 attenuation = MSG_ReadByte () / 64.0;
147         else
148                 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
149         
150         channel = MSG_ReadShort ();
151         if (largesoundindex)
152                 sound_num = (unsigned short) MSG_ReadShort ();
153         else
154                 sound_num = MSG_ReadByte ();
155
156         if (sound_num >= MAX_SOUNDS)
157                 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
158
159         ent = channel >> 3;
160         channel &= 7;
161
162         if (ent > MAX_EDICTS)
163                 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
164         
165         for (i=0 ; i<3 ; i++)
166                 pos[i] = MSG_ReadCoord ();
167  
168     S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
169 }       
170
171 /*
172 ==================
173 CL_KeepaliveMessage
174
175 When the client is taking a long time to load stuff, send keepalive messages
176 so the server doesn't disconnect.
177 ==================
178 */
179 void CL_KeepaliveMessage (void)
180 {
181         float   time;
182         static float lastmsg;
183         int             ret;
184         sizebuf_t       old;
185         byte            olddata[8192];
186         
187         if (sv.active)
188                 return;         // no need if server is local
189         if (cls.demoplayback)
190                 return;
191
192 // read messages from server, should just be nops
193         old = net_message;
194         memcpy (olddata, net_message.data, net_message.cursize);
195         
196         do
197         {
198                 ret = CL_GetMessage ();
199                 switch (ret)
200                 {
201                 default:
202                         Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");               
203                 case 0:
204                         break;  // nothing waiting
205                 case 1:
206                         Host_Error ("CL_KeepaliveMessage: received a message");
207                         break;
208                 case 2:
209                         if (MSG_ReadByte() != svc_nop)
210                                 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
211                         break;
212                 }
213         } while (ret);
214
215         net_message = old;
216         memcpy (net_message.data, olddata, net_message.cursize);
217
218 // check time
219         time = Sys_FloatTime ();
220         if (time - lastmsg < 5)
221                 return;
222         lastmsg = time;
223
224 // write out a nop
225         Con_Printf ("--> client to server keepalive\n");
226
227         MSG_WriteByte (&cls.message, clc_nop);
228         NET_SendMessage (cls.netcon, &cls.message);
229         SZ_Clear (&cls.message);
230 }
231
232 extern qboolean isworldmodel;
233 extern char skyname[];
234 extern void R_SetSkyBox (char *sky);
235 extern void FOG_clear();
236 extern cvar_t r_farclip;
237
238 void CL_ParseEntityLump(char *entdata)
239 {
240         char *data;
241         char key[128], value[4096];
242         char wadname[128];
243         int i, j, k;
244         FOG_clear(); // LordHavoc: no fog until set
245         skyname[0] = 0; // LordHavoc: no enviroment mapped sky until set
246         r_farclip.value = 6144; // LordHavoc: default farclip distance
247         data = entdata;
248         if (!data)
249                 return;
250         data = COM_Parse(data);
251         if (!data)
252                 return; // valid exit
253         if (com_token[0] != '{')
254                 return; // error
255         while (1)
256         {
257                 data = COM_Parse(data);
258                 if (!data)
259                         return; // error
260                 if (com_token[0] == '}')
261                         return; // since we're just parsing the first ent (worldspawn), exit
262                 strcpy(key, com_token);
263                 while (key[strlen(key)-1] == ' ') // remove trailing spaces
264                         key[strlen(key)-1] = 0;
265                 data = COM_Parse(data);
266                 if (!data)
267                         return; // error
268                 strcpy(value, com_token);
269                 if (!strcmp("sky", key))
270                         R_SetSkyBox(value);
271                 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
272                         R_SetSkyBox(value);
273                 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
274                         R_SetSkyBox(value);
275                 else if (!strcmp("farclip", key))
276                 {
277                         r_farclip.value = atof(value);
278                         if (r_farclip.value < 64)
279                                 r_farclip.value = 64;
280                 }
281                 else if (!strcmp("fog", key))
282                 {
283                         scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
284                         j = 0;
285                 }
286                 else if (!strcmp("fog_density", key))
287                         fog_density = atof(value);
288                 else if (!strcmp("fog_red", key))
289                         fog_red = atof(value);
290                 else if (!strcmp("fog_green", key))
291                         fog_green = atof(value);
292                 else if (!strcmp("fog_blue", key))
293                         fog_blue = atof(value);
294                 else if (!strcmp("wad", key)) // for HalfLife maps
295                 {
296                         j = 0;
297                         for (i = 0;i < 4096;i++)
298                                 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
299                                         break;
300                         if (value[i])
301                         {
302                                 for (;i < 4096;i++)
303                                 {
304                                         // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
305                                         if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
306                                                 j = i+1;
307                                         else if (value[i] == ';' || value[i] == 0)
308                                         {
309                                                 k = value[i];
310                                                 value[i] = 0;
311                                                 strcpy(wadname, "textures/");
312                                                 strcat(wadname, &value[j]);
313                                                 W_LoadTextureWadFile (wadname, false);
314                                                 j = i+1;
315                                                 if (!k)
316                                                         break;
317                                         }
318                                 }
319                         }
320                 }
321         }
322 }
323
324 /*
325 ==================
326 CL_ParseServerInfo
327 ==================
328 */
329 extern cvar_t demo_nehahra;
330 void CL_ParseServerInfo (void)
331 {
332         char    *str;
333         int             i;
334         int             nummodels, numsounds;
335         char    model_precache[MAX_MODELS][MAX_QPATH];
336         char    sound_precache[MAX_SOUNDS][MAX_QPATH];
337         
338         Con_DPrintf ("Serverinfo packet received.\n");
339 //
340 // wipe the client_state_t struct
341 //
342         CL_ClearState ();
343
344 // parse protocol version number
345         i = MSG_ReadLong ();
346         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
347         {
348                 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
349                 return;
350         }
351         Nehahrademcompatibility = false;
352         if (i == 250)
353                 Nehahrademcompatibility = true;
354         if (cls.demoplayback && demo_nehahra.value)
355                 Nehahrademcompatibility = true;
356         dpprotocol = i == DPPROTOCOL_VERSION;
357
358 // parse maxclients
359         cl.maxclients = MSG_ReadByte ();
360         if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
361         {
362                 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
363                 return;
364         }
365         cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
366
367 // parse gametype
368         cl.gametype = MSG_ReadByte ();
369
370 // parse signon message
371         str = MSG_ReadString ();
372         strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
373
374 // seperate the printfs so the server message can have a color
375         if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
376         {
377                 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");
378                 Con_Printf ("%c%s\n", 2, str);
379         }
380
381 //
382 // first we go through and touch all of the precache data that still
383 // happens to be in the cache, so precaching something else doesn't
384 // needlessly purge it
385 //
386
387 // precache models
388         memset (cl.model_precache, 0, sizeof(cl.model_precache));
389         for (nummodels=1 ; ; nummodels++)
390         {
391                 str = MSG_ReadString ();
392                 if (!str[0])
393                         break;
394                 if (nummodels==MAX_MODELS)
395                 {
396                         Con_Printf ("Server sent too many model precaches\n");
397                         return;
398                 }
399                 if (strlen(str) >= MAX_QPATH)
400                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
401                 strcpy (model_precache[nummodels], str);
402                 Mod_TouchModel (str);
403         }
404
405 // precache sounds
406         memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
407         for (numsounds=1 ; ; numsounds++)
408         {
409                 str = MSG_ReadString ();
410                 if (!str[0])
411                         break;
412                 if (numsounds==MAX_SOUNDS)
413                 {
414                         Con_Printf ("Server sent too many sound precaches\n");
415                         return;
416                 }
417                 if (strlen(str) >= MAX_QPATH)
418                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
419                 strcpy (sound_precache[numsounds], str);
420                 S_TouchSound (str);
421         }
422
423 //
424 // now we try to load everything else until a cache allocation fails
425 //
426
427         for (i=1 ; i<nummodels ; i++)
428         {
429                 isworldmodel = i == 1; // LordHavoc: first model is the world model
430                 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
431                 if (cl.model_precache[i] == NULL)
432                 {
433                         Con_Printf("Model %s not found\n", model_precache[i]);
434                         return;
435                 }
436                 CL_KeepaliveMessage ();
437         }
438
439         S_BeginPrecaching ();
440         for (i=1 ; i<numsounds ; i++)
441         {
442                 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
443                 CL_KeepaliveMessage ();
444         }
445         S_EndPrecaching ();
446
447
448 // local state
449         cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
450         
451         R_NewMap ();
452
453         Hunk_Check ();          // make sure nothing is hurt
454         
455         noclip_anglehack = false;               // noclip is turned off at start        
456 }
457
458 void CL_ValidateState(entity_state_t *s)
459 {
460         model_t *model;
461
462         if (s->modelindex >= MAX_MODELS)
463                 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
464
465         // colormap is client index + 1
466         if (s->colormap > cl.maxclients)
467                 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
468
469         model = cl.model_precache[s->modelindex];
470         if (model && s->frame >= model->numframes)
471         {
472                 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
473                 s->frame = 0;
474         }
475 }
476
477 /*
478 ==================
479 CL_ParseUpdate
480
481 Parse an entity update message from the server
482 If an entities model or origin changes from frame to frame, it must be
483 relinked.  Other attributes can change without relinking.
484 ==================
485 */
486 byte entkill[MAX_EDICTS];
487 void CL_ParseUpdate (int bits)
488 {
489         int num, deltadie;
490         entity_t *ent;
491
492         if (cls.signon == SIGNONS - 1)
493         {       // first update is the final signon stage
494                 cls.signon = SIGNONS;
495                 CL_SignonReply ();
496         }
497
498         if (bits & U_MOREBITS)
499                 bits |= (MSG_ReadByte()<<8);
500         if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
501         {
502                 bits |= MSG_ReadByte() << 16;
503                 if (bits & U_EXTEND2)
504                         bits |= MSG_ReadByte() << 24;
505         }
506
507         if (bits & U_LONGENTITY)        
508                 num = (unsigned) MSG_ReadShort ();
509         else
510                 num = (unsigned) MSG_ReadByte ();
511
512         if (num >= MAX_EDICTS)
513                 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
514         if (num < 1)
515                 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
516
517         // mark as visible (no kill)
518         entkill[num] = 0;
519
520         ent = CL_EntityNum (num);
521
522         ent->state_previous = ent->state_current;
523         deltadie = false;
524         if (bits & U_DELTA)
525         {
526                 if (!ent->state_current.modelindex)
527                         deltadie = true; // was not present in previous frame, leave hidden until next full update
528         }
529         else
530                 ent->state_current = ent->state_baseline;
531
532         ent->state_current.time = cl.mtime[0];
533
534         ent->state_current.flags = 0;
535         if (bits & U_MODEL)             ent->state_current.modelindex = (ent->state_current.modelindex & 0xFF00) | MSG_ReadByte();
536         if (bits & U_FRAME)             ent->state_current.frame = (ent->state_current.frame & 0xFF00) | MSG_ReadByte();
537         if (bits & U_COLORMAP)  ent->state_current.colormap = MSG_ReadByte();
538         if (bits & U_SKIN)              ent->state_current.skin = MSG_ReadByte();
539         if (bits & U_EFFECTS)   ent->state_current.effects = (ent->state_current.effects & 0xFF00) | MSG_ReadByte();
540         if (bits & U_ORIGIN1)   ent->state_current.origin[0] = MSG_ReadCoord();
541         if (bits & U_ANGLE1)    ent->state_current.angles[0] = MSG_ReadAngle();
542         if (bits & U_ORIGIN2)   ent->state_current.origin[1] = MSG_ReadCoord();
543         if (bits & U_ANGLE2)    ent->state_current.angles[1] = MSG_ReadAngle();
544         if (bits & U_ORIGIN3)   ent->state_current.origin[2] = MSG_ReadCoord();
545         if (bits & U_ANGLE3)    ent->state_current.angles[2] = MSG_ReadAngle();
546         if (bits & U_STEP)              ent->state_current.flags |= RENDER_STEP;
547         if (bits & U_ALPHA)             ent->state_current.alpha = MSG_ReadByte();
548         if (bits & U_SCALE)             ent->state_current.scale = MSG_ReadByte();
549         if (bits & U_EFFECTS2)  ent->state_current.effects = (ent->state_current.effects & 0x00FF) | (MSG_ReadByte() << 8);
550         if (bits & U_GLOWSIZE)  ent->state_current.glowsize = MSG_ReadByte();
551         if (bits & U_GLOWCOLOR) ent->state_current.glowcolor = MSG_ReadByte();
552         if (bits & U_GLOWTRAIL) ent->state_current.flags |= RENDER_GLOWTRAIL;
553         if (bits & U_COLORMOD)  ent->state_current.colormod = MSG_ReadByte();
554         if (bits & U_FRAME2)    ent->state_current.frame = (ent->state_current.frame & 0x00FF) | (MSG_ReadByte() << 8);
555         if (bits & U_MODEL2)    ent->state_current.modelindex = (ent->state_current.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
556         if (bits & U_VIEWMODEL) ent->state_current.flags |= RENDER_VIEWMODEL;
557
558         // LordHavoc: to allow playback of the Nehahra movie
559         if (Nehahrademcompatibility && (bits & U_EXTEND1))
560         {
561                 // LordHavoc: evil format
562                 int i = MSG_ReadFloat();
563                 int j = MSG_ReadFloat() * 255.0f;
564                 if (i == 2)
565                 {
566                         if (MSG_ReadFloat())
567                                 ent->state_current.effects |= EF_FULLBRIGHT;
568                 }
569                 if (j < 0)
570                         ent->state_current.alpha = 0;
571                 else if (j == 0 || j >= 255)
572                         ent->state_current.alpha = 255;
573                 else
574                         ent->state_current.alpha = j;
575         }
576
577         if (deltadie)
578         {
579                 // hide the entity
580                 ent->state_current.modelindex = 0;
581         }
582         else
583         {
584                 CL_ValidateState(&ent->state_current);
585
586                 /*
587                 if (!ent->state_current.modelindex)
588                 {
589                         if (bits & U_DELTA)
590                         {
591                                 if (bits & U_MODEL)
592                                         Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i %i\n", num, ent->state_previous.modelindex, ent->state_current.modelindex);
593                                 else
594                                         Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i\n", num, ent->state_previous.modelindex);
595                         }
596                         else
597                         {
598                                 if (bits & U_MODEL)
599                                         Con_Printf("CL_ParseUpdate:       NULL model on %i: %i %i\n", num, ent->state_baseline.modelindex, ent->state_current.modelindex);
600                                 else
601                                         Con_Printf("CL_ParseUpdate:       NULL model on %i: %i\n", num, ent->state_baseline.modelindex);
602                         }
603                 }
604                 */
605         }
606 }
607
608 int entityupdatestart;
609 void CL_EntityUpdateBegin(int start)
610 {
611         if (start < 0 || start >= MAX_EDICTS)
612                 Host_Error("CL_EntityUpdateBegin: start (%i) < 0 or >= MAX_EDICTS (%i)\n", start, MAX_EDICTS);
613         entityupdatestart = start;
614         memset(entkill, 1, MAX_EDICTS);
615 }
616
617 void CL_EntityUpdateEnd(int end)
618 {
619         int i;
620         if (end < 0 || end > MAX_EDICTS)
621                 Host_Error("CL_EntityUpdateEnd: end (%i) < 0 or > MAX_EDICTS (%i)\n", end, MAX_EDICTS);
622         for (i = entityupdatestart;i < end;i++)
623                 if (entkill[i])
624                         cl_entities[i].state_current.modelindex = 0;
625 }
626
627 /*
628 ==================
629 CL_ParseBaseline
630 ==================
631 */
632 void CL_ParseBaseline (entity_t *ent, int largemodelindex)
633 {
634         int i;
635
636         memset(&ent->state_baseline, 0, sizeof(entity_state_t));
637         if (largemodelindex)
638                 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
639         else
640                 ent->state_baseline.modelindex = MSG_ReadByte ();
641         ent->state_baseline.frame = MSG_ReadByte ();
642         ent->state_baseline.colormap = MSG_ReadByte();
643         ent->state_baseline.skin = MSG_ReadByte();
644         for (i = 0;i < 3;i++)
645         {
646                 ent->state_baseline.origin[i] = MSG_ReadCoord ();
647                 ent->state_baseline.angles[i] = MSG_ReadAngle ();
648         }
649         ent->state_baseline.alpha = 255;
650         ent->state_baseline.scale = 16;
651         ent->state_baseline.glowsize = 0;
652         ent->state_baseline.glowcolor = 254;
653         ent->state_baseline.colormod = 255;
654         ent->state_previous = ent->state_current = ent->state_baseline;
655
656         CL_ValidateState(&ent->state_baseline);
657 }
658
659
660 /*
661 ==================
662 CL_ParseClientdata
663
664 Server information pertaining to this client only
665 ==================
666 */
667 void CL_ParseClientdata (int bits)
668 {
669         int i, j;
670
671         bits &= 0xFFFF;
672         if (bits & SU_EXTEND1)
673                 bits |= (MSG_ReadByte() << 16);
674         if (bits & SU_EXTEND2)
675                 bits |= (MSG_ReadByte() << 24);
676
677         if (bits & SU_VIEWHEIGHT)
678                 cl.viewheight = MSG_ReadChar ();
679         else
680                 cl.viewheight = DEFAULT_VIEWHEIGHT;
681
682         if (bits & SU_IDEALPITCH)
683                 cl.idealpitch = MSG_ReadChar ();
684         else
685                 cl.idealpitch = 0;
686         
687         VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
688         for (i=0 ; i<3 ; i++)
689         {
690                 if (bits & (SU_PUNCH1<<i) )
691                 {
692                         if (dpprotocol)
693                                 cl.punchangle[i] = MSG_ReadPreciseAngle();
694                         else
695                                 cl.punchangle[i] = MSG_ReadChar();
696                 }
697                 else
698                         cl.punchangle[i] = 0;
699                 if (bits & (SU_PUNCHVEC1<<i))
700                         cl.punchvector[i] = MSG_ReadFloatCoord();
701                 else
702                         cl.punchvector[i] = 0;
703                 if (bits & (SU_VELOCITY1<<i) )
704                         cl.mvelocity[0][i] = MSG_ReadChar()*16;
705                 else
706                         cl.mvelocity[0][i] = 0;
707         }
708
709         i = MSG_ReadLong ();
710         if (cl.items != i)
711         {       // set flash times
712                 for (j=0 ; j<32 ; j++)
713                         if ( (i & (1<<j)) && !(cl.items & (1<<j)))
714                                 cl.item_gettime[j] = cl.time;
715                 cl.items = i;
716         }
717                 
718         cl.onground = (bits & SU_ONGROUND) != 0;
719         cl.inwater = (bits & SU_INWATER) != 0;
720
721         cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
722         cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
723         cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
724         cl.stats[STAT_HEALTH] = MSG_ReadShort();
725         cl.stats[STAT_AMMO] = MSG_ReadByte();
726
727         cl.stats[STAT_SHELLS] = MSG_ReadByte();
728         cl.stats[STAT_NAILS] = MSG_ReadByte();
729         cl.stats[STAT_ROCKETS] = MSG_ReadByte();
730         cl.stats[STAT_CELLS] = MSG_ReadByte();
731
732         i = MSG_ReadByte ();
733
734         if (standard_quake)
735                 cl.stats[STAT_ACTIVEWEAPON] = i;
736         else
737                 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
738 }
739
740 /*
741 =====================
742 CL_ParseStatic
743 =====================
744 */
745 void CL_ParseStatic (int largemodelindex)
746 {
747         entity_t *ent;
748                 
749         if (cl.num_statics >= MAX_STATIC_ENTITIES)
750                 Host_Error ("Too many static entities");
751         ent = &cl_static_entities[cl.num_statics++];
752         CL_ParseBaseline (ent, largemodelindex);
753
754 // copy it to the current state
755         ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
756         ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
757         ent->render.framelerp = 0;
758         ent->render.lerp_starttime = -1;
759         // make torchs play out of sync
760         ent->render.frame1start = ent->render.frame2start = -(rand() & 32767);
761         ent->render.colormap = -1; // no special coloring
762         ent->render.skinnum = ent->state_baseline.skin;
763         ent->render.effects = ent->state_baseline.effects;
764         ent->render.alpha = 1;
765         ent->render.scale = 1;
766         ent->render.alpha = 1;
767         ent->render.glowsize = 0;
768         ent->render.glowcolor = 254;
769         ent->render.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
770
771         VectorCopy (ent->state_baseline.origin, ent->render.origin);
772         VectorCopy (ent->state_baseline.angles, ent->render.angles);    
773         R_AddEfrags (ent);
774 }
775
776 /*
777 ===================
778 CL_ParseStaticSound
779 ===================
780 */
781 void CL_ParseStaticSound (void)
782 {
783         vec3_t          org;
784         int                     sound_num, vol, atten;
785
786         MSG_ReadVector(org);
787         sound_num = MSG_ReadByte ();
788         vol = MSG_ReadByte ();
789         atten = MSG_ReadByte ();
790         
791         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
792 }
793
794 void CL_ParseEffect (void)
795 {
796         vec3_t          org;
797         int                     modelindex, startframe, framecount, framerate;
798
799         MSG_ReadVector(org);
800         modelindex = MSG_ReadByte ();
801         startframe = MSG_ReadByte ();
802         framecount = MSG_ReadByte ();
803         framerate = MSG_ReadByte ();
804
805         CL_Effect(org, modelindex, startframe, framecount, framerate);
806 }
807
808 void CL_ParseEffect2 (void)
809 {
810         vec3_t          org;
811         int                     modelindex, startframe, framecount, framerate;
812
813         MSG_ReadVector(org);
814         modelindex = MSG_ReadShort ();
815         startframe = MSG_ReadByte ();
816         framecount = MSG_ReadByte ();
817         framerate = MSG_ReadByte ();
818
819         CL_Effect(org, modelindex, startframe, framecount, framerate);
820 }
821
822
823 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
824
825 extern void SHOWLMP_decodehide();
826 extern void SHOWLMP_decodeshow();
827 extern void R_SetSkyBox(char* sky);
828 extern int netshown;
829
830 /*
831 =====================
832 CL_ParseServerMessage
833 =====================
834 */
835 void CL_ParseServerMessage (void)
836 {
837         int                     cmd;
838         int                     i, updateend;
839         byte            cmdlog[32];
840         char            *cmdlogname[32], *temp;
841         int                     cmdindex, cmdcount = 0;
842         
843 //
844 // if recording demos, copy the message out
845 //
846         if (cl_shownet.value == 1)
847         {
848                 Con_Printf ("%i ",net_message.cursize);
849                 netshown = true;
850         }
851         else if (cl_shownet.value == 2)
852         {
853                 Con_Printf ("------------------\n");
854                 netshown = true;
855         }
856         
857         cl.onground = false;    // unless the server says otherwise     
858 //
859 // parse the message
860 //
861         MSG_BeginReading ();
862
863         updateend = false;
864         
865         while (1)
866         {
867                 if (msg_badread)
868                         Host_Error ("CL_ParseServerMessage: Bad server message");
869
870                 cmd = MSG_ReadByte ();
871
872                 if (cmd == -1)
873                 {
874                         SHOWNET("END OF MESSAGE");
875                         break;          // end of message
876                 }
877
878                 cmdindex = cmdcount & 31;
879                 cmdcount++;
880                 cmdlog[cmdindex] = cmd;
881
882                 // if the high bit of the command byte is set, it is a fast update
883                 if (cmd & 128)
884                 {
885                         // 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)
886                         temp = "entity";
887                         cmdlogname[cmdindex] = temp;
888                         SHOWNET("fast update");
889                         CL_ParseUpdate (cmd&127);
890                         continue;
891                 }
892
893                 SHOWNET(svc_strings[cmd]);
894                 cmdlogname[cmdindex] = svc_strings[cmd];
895                 if (!cmdlogname[cmdindex])
896                 {
897                         // 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)
898                         temp = "<unknown>";
899                         cmdlogname[cmdindex] = temp;
900                 }
901         
902                 // other commands
903                 switch (cmd)
904                 {
905                 default:
906                         {
907                                 char description[32*64], temp[64];
908                                 int count;
909                                 strcpy(description, "packet dump: ");
910                                 i = cmdcount - 32;
911                                 if (i < 0)
912                                         i = 0;
913                                 count = cmdcount - i;
914                                 i &= 31;
915                                 while(count > 0)
916                                 {
917                                         sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
918                                         strcat(description, temp);
919                                         count--;
920                                         i++;
921                                         i &= 31;
922                                 }
923                                 description[strlen(description)-1] = '\n'; // replace the last space with a newline
924                                 Con_Printf(description);
925                                 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
926                         }
927                         break;
928                         
929                 case svc_nop:
930 //                      Con_Printf ("svc_nop\n");
931                         break;
932                         
933                 case svc_time:
934                         // handle old protocols which do not have entity update ranges
935                         CL_EntityUpdateBegin(0);
936                         updateend = true;
937                         cl.mtime[1] = cl.mtime[0];
938                         cl.mtime[0] = MSG_ReadFloat ();                 
939                         break;
940                         
941                 case svc_clientdata:
942                         i = MSG_ReadShort ();
943                         CL_ParseClientdata (i);
944                         break;
945                 
946                 case svc_version:
947                         i = MSG_ReadLong ();
948                         if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
949                                 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
950                         Nehahrademcompatibility = false;
951                         if (i == 250)
952                                 Nehahrademcompatibility = true;
953                         if (cls.demoplayback && demo_nehahra.value)
954                                 Nehahrademcompatibility = true;
955                         dpprotocol = i == DPPROTOCOL_VERSION;
956                         break;
957                         
958                 case svc_disconnect:
959                         Host_EndGame ("Server disconnected\n");
960
961                 case svc_print:
962                         Con_Printf ("%s", MSG_ReadString ());
963                         break;
964                         
965                 case svc_centerprint:
966                         SCR_CenterPrint (MSG_ReadString ());
967                         break;
968                         
969                 case svc_stufftext:
970                         Cbuf_AddText (MSG_ReadString ());
971                         break;
972                         
973                 case svc_damage:
974                         V_ParseDamage ();
975                         break;
976                         
977                 case svc_serverinfo:
978                         CL_ParseServerInfo ();
979                         vid.recalc_refdef = true;       // leave intermission full screen
980                         break;
981                         
982                 case svc_setangle:
983                         for (i=0 ; i<3 ; i++)
984                                 cl.viewangles[i] = MSG_ReadAngle ();
985                         break;
986                         
987                 case svc_setview:
988                         cl.viewentity = MSG_ReadShort ();
989                         break;
990                                         
991                 case svc_lightstyle:
992                         i = MSG_ReadByte ();
993                         if (i >= MAX_LIGHTSTYLES)
994                                 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
995                         strncpy (cl_lightstyle[i].map,  MSG_ReadString(), MAX_STYLESTRING - 1);
996                         cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
997                         cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
998                         break;
999                         
1000                 case svc_sound:
1001                         CL_ParseStartSoundPacket(false);
1002                         break;
1003
1004                 case svc_sound2:
1005                         CL_ParseStartSoundPacket(true);
1006                         break;
1007
1008                 case svc_stopsound:
1009                         i = MSG_ReadShort();
1010                         S_StopSound(i>>3, i&7);
1011                         break;
1012                 
1013                 case svc_updatename:
1014                         i = MSG_ReadByte ();
1015                         if (i >= cl.maxclients)
1016                                 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1017                         strcpy (cl.scores[i].name, MSG_ReadString ());
1018                         break;
1019                         
1020                 case svc_updatefrags:
1021                         i = MSG_ReadByte ();
1022                         if (i >= cl.maxclients)
1023                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1024                         cl.scores[i].frags = MSG_ReadShort ();
1025                         break;                  
1026
1027                 case svc_updatecolors:
1028                         i = MSG_ReadByte ();
1029                         if (i >= cl.maxclients)
1030                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1031                         cl.scores[i].colors = MSG_ReadByte ();
1032                         break;
1033                         
1034                 case svc_particle:
1035                         R_ParseParticleEffect ();
1036                         break;
1037
1038                 case svc_effect:
1039                         CL_ParseEffect ();
1040                         break;
1041
1042                 case svc_effect2:
1043                         CL_ParseEffect2 ();
1044                         break;
1045
1046                 case svc_spawnbaseline:
1047                         i = MSG_ReadShort ();
1048                         // must use CL_EntityNum() to force cl.num_entities up
1049                         CL_ParseBaseline (CL_EntityNum(i), false);
1050                         break;
1051                 case svc_spawnbaseline2:
1052                         i = MSG_ReadShort ();
1053                         // must use CL_EntityNum() to force cl.num_entities up
1054                         CL_ParseBaseline (CL_EntityNum(i), false);
1055                         break;
1056                 case svc_spawnstatic:
1057                         CL_ParseStatic (false);
1058                         break;
1059                 case svc_spawnstatic2:
1060                         CL_ParseStatic (true);
1061                         break;
1062                 case svc_temp_entity:
1063                         CL_ParseTEnt ();
1064                         break;
1065
1066                 case svc_setpause:
1067                         cl.paused = MSG_ReadByte ();
1068                         if (cl.paused)
1069                                 CDAudio_Pause ();
1070                         else
1071                                 CDAudio_Resume ();
1072                         break;
1073                         
1074                 case svc_signonnum:
1075                         i = MSG_ReadByte ();
1076                         if (i <= cls.signon)
1077                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
1078                         cls.signon = i;
1079                         CL_SignonReply ();
1080                         break;
1081
1082                 case svc_killedmonster:
1083                         cl.stats[STAT_MONSTERS]++;
1084                         break;
1085
1086                 case svc_foundsecret:
1087                         cl.stats[STAT_SECRETS]++;
1088                         break;
1089
1090                 case svc_updatestat:
1091                         i = MSG_ReadByte ();
1092                         if (i < 0 || i >= MAX_CL_STATS)
1093                                 Host_Error ("svc_updatestat: %i is invalid", i);
1094                         cl.stats[i] = MSG_ReadLong ();
1095                         break;
1096                         
1097                 case svc_spawnstaticsound:
1098                         CL_ParseStaticSound ();
1099                         break;
1100
1101                 case svc_cdtrack:
1102                         cl.cdtrack = MSG_ReadByte ();
1103                         cl.looptrack = MSG_ReadByte ();
1104                         if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1105                                 CDAudio_Play ((byte)cls.forcetrack, true);
1106                         else
1107                                 CDAudio_Play ((byte)cl.cdtrack, true);
1108                         break;
1109
1110                 case svc_intermission:
1111                         cl.intermission = 1;
1112                         cl.completed_time = cl.time;
1113                         vid.recalc_refdef = true;       // go to full screen
1114                         break;
1115
1116                 case svc_finale:
1117                         cl.intermission = 2;
1118                         cl.completed_time = cl.time;
1119                         vid.recalc_refdef = true;       // go to full screen
1120                         SCR_CenterPrint (MSG_ReadString ());                    
1121                         break;
1122
1123                 case svc_cutscene:
1124                         cl.intermission = 3;
1125                         cl.completed_time = cl.time;
1126                         vid.recalc_refdef = true;       // go to full screen
1127                         SCR_CenterPrint (MSG_ReadString ());                    
1128                         break;
1129
1130                 case svc_sellscreen:
1131                         Cmd_ExecuteString ("help", src_command);
1132                         break;
1133                 case svc_hidelmp:
1134                         SHOWLMP_decodehide();
1135                         break;
1136                 case svc_showlmp:
1137                         SHOWLMP_decodeshow();
1138                         break;
1139                 case svc_entitiesbegin:
1140                         // the beginning of an entity update range
1141                         CL_EntityUpdateBegin((unsigned) MSG_ReadShort());
1142                         break;
1143                 case svc_entitiesend:
1144                         // the end of an entity update range
1145                         CL_EntityUpdateEnd((unsigned) MSG_ReadShort());
1146                         updateend = false;
1147                         break;
1148                 }
1149         }
1150
1151         if (updateend)
1152                 CL_EntityUpdateEnd(MAX_EDICTS);
1153 }
1154