]> git.xonotic.org Git - xonotic/darkplaces.git/blob - cl_parse.c
1db4e0a6b4d35c718064946eecb1aef539432c7d
[xonotic/darkplaces.git] / cl_parse.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // cl_parse.c  -- parse a message received from the server
21
22 #include "quakedef.h"
23 #include "cl_collision.h"
24
25 char *svc_strings[128] =
26 {
27         "svc_bad",
28         "svc_nop",
29         "svc_disconnect",
30         "svc_updatestat",
31         "svc_version",          // [long] server version
32         "svc_setview",          // [short] entity number
33         "svc_sound",                    // <see code>
34         "svc_time",                     // [float] server time
35         "svc_print",                    // [string] null terminated string
36         "svc_stufftext",                // [string] stuffed into client's console buffer
37                                                 // the string should be \n terminated
38         "svc_setangle",         // [vec3] set the view angle to this absolute value
39
40         "svc_serverinfo",               // [long] version
41                                                 // [string] signon string
42                                                 // [string]..[0]model cache [string]...[0]sounds cache
43                                                 // [string]..[0]item cache
44         "svc_lightstyle",               // [byte] [string]
45         "svc_updatename",               // [byte] [string]
46         "svc_updatefrags",      // [byte] [short]
47         "svc_clientdata",               // <shortbits + data>
48         "svc_stopsound",                // <see code>
49         "svc_updatecolors",     // [byte] [byte]
50         "svc_particle",         // [vec3] <variable>
51         "svc_damage",                   // [byte] impact [byte] blood [vec3] from
52
53         "svc_spawnstatic",
54         "OBSOLETE svc_spawnbinary",
55         "svc_spawnbaseline",
56
57         "svc_temp_entity",              // <variable>
58         "svc_setpause",
59         "svc_signonnum",
60         "svc_centerprint",
61         "svc_killedmonster",
62         "svc_foundsecret",
63         "svc_spawnstaticsound",
64         "svc_intermission",
65         "svc_finale",                   // [string] music [string] text
66         "svc_cdtrack",                  // [byte] track [byte] looptrack
67         "svc_sellscreen",
68         "svc_cutscene",
69         "svc_showlmp",  // [string] iconlabel [string] lmpfile [short] x [short] y
70         "svc_hidelmp",  // [string] iconlabel
71         "svc_skybox", // [string] skyname
72         "", // 38
73         "", // 39
74         "", // 40
75         "", // 41
76         "", // 42
77         "", // 43
78         "", // 44
79         "", // 45
80         "", // 46
81         "", // 47
82         "", // 48
83         "", // 49
84         "svc_cgame", //                         50              // [short] length [bytes] data
85         "svc_unusedlh1", //                     51              // unused
86         "svc_effect", //                        52              // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
87         "svc_effect2", //                       53              // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
88         "svc_sound2", //                        54              // short soundindex instead of byte
89         "svc_spawnbaseline2", //        55              // short modelindex instead of byte
90         "svc_spawnstatic2", //          56              // short modelindex instead of byte
91         "svc_entities", //                      57              // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata
92         "svc_unusedlh3", //                     58
93         "svc_spawnstaticsound2", //     59              // [coord3] [short] samp [byte] vol [byte] aten
94 };
95
96 //=============================================================================
97
98 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
99 cvar_t developer_networkentities = {0, "developer_networkentities", "0"};
100
101 mempool_t *cl_scores_mempool;
102
103 /*
104 ==================
105 CL_ParseStartSoundPacket
106 ==================
107 */
108 void CL_ParseStartSoundPacket(int largesoundindex)
109 {
110         vec3_t  pos;
111         int     channel, ent;
112         int     sound_num;
113         int     volume;
114         int     field_mask;
115         float   attenuation;
116
117         field_mask = MSG_ReadByte();
118
119         if (field_mask & SND_VOLUME)
120                 volume = MSG_ReadByte ();
121         else
122                 volume = DEFAULT_SOUND_PACKET_VOLUME;
123
124         if (field_mask & SND_ATTENUATION)
125                 attenuation = MSG_ReadByte () / 64.0;
126         else
127                 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
128
129         if (field_mask & SND_LARGEENTITY)
130         {
131                 ent = (unsigned short) MSG_ReadShort ();
132                 channel = MSG_ReadByte ();
133         }
134         else
135         {
136                 channel = (unsigned short) MSG_ReadShort ();
137                 ent = channel >> 3;
138                 channel &= 7;
139         }
140
141         if (largesoundindex || field_mask & SND_LARGESOUND)
142                 sound_num = (unsigned short) MSG_ReadShort ();
143         else
144                 sound_num = MSG_ReadByte ();
145
146         if (sound_num >= MAX_SOUNDS)
147                 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
148
149
150         if (ent >= MAX_EDICTS)
151                 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
152
153         MSG_ReadVector(pos);
154
155         S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
156 }
157
158 /*
159 ==================
160 CL_KeepaliveMessage
161
162 When the client is taking a long time to load stuff, send keepalive messages
163 so the server doesn't disconnect.
164 ==================
165 */
166
167 static qbyte olddata[NET_MAXMESSAGE];
168 void CL_KeepaliveMessage (void)
169 {
170         float time;
171         static float lastmsg;
172         int oldreadcount;
173         qboolean oldbadread;
174         sizebuf_t old;
175
176         // no need if server is local and definitely not if this is a demo
177         if (sv.active || cls.demoplayback)
178                 return;
179
180 // read messages from server, should just be nops
181         oldreadcount = msg_readcount;
182         oldbadread = msg_badread;
183         old = net_message;
184         memcpy(olddata, net_message.data, net_message.cursize);
185
186         NetConn_ClientFrame();
187
188         msg_readcount = oldreadcount;
189         msg_badread = oldbadread;
190         net_message = old;
191         memcpy(net_message.data, olddata, net_message.cursize);
192
193         if (cls.netcon && NetConn_CanSendMessage(cls.netcon) && (time = Sys_DoubleTime()) - lastmsg >= 5)
194         {
195                 sizebuf_t       msg;
196                 qbyte           buf[4];
197                 lastmsg = time;
198                 // write out a nop
199                 // LordHavoc: must use unreliable because reliable could kill the sigon message!
200                 Con_Print("--> client to server keepalive\n");
201                 msg.data = buf;
202                 msg.maxsize = sizeof(buf);
203                 msg.cursize = 0;
204                 MSG_WriteChar(&msg, svc_nop);
205                 NetConn_SendUnreliableMessage(cls.netcon, &msg);
206                 // try not to utterly crush the computer with work, that's just rude
207                 Sys_Sleep(1);
208         }
209 }
210
211 void CL_ParseEntityLump(char *entdata)
212 {
213         const char *data;
214         char key[128], value[4096];
215         FOG_clear(); // LordHavoc: no fog until set
216         // LordHavoc: default to the map's sky (q3 shader parsing sets this)
217         R_SetSkyBox(cl.worldmodel->brush.skybox);
218         data = entdata;
219         if (!data)
220                 return;
221         if (!COM_ParseToken(&data, false))
222                 return; // error
223         if (com_token[0] != '{')
224                 return; // error
225         while (1)
226         {
227                 if (!COM_ParseToken(&data, false))
228                         return; // error
229                 if (com_token[0] == '}')
230                         break; // end of worldspawn
231                 if (com_token[0] == '_')
232                         strlcpy (key, com_token + 1, sizeof (key));
233                 else
234                         strlcpy (key, com_token, sizeof (key));
235                 while (key[strlen(key)-1] == ' ') // remove trailing spaces
236                         key[strlen(key)-1] = 0;
237                 if (!COM_ParseToken(&data, false))
238                         return; // error
239                 strlcpy (value, com_token, sizeof (value));
240                 if (!strcmp("sky", key))
241                         R_SetSkyBox(value);
242                 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
243                         R_SetSkyBox(value);
244                 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
245                         R_SetSkyBox(value);
246                 else if (!strcmp("fog", key))
247                         sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
248                 else if (!strcmp("fog_density", key))
249                         fog_density = atof(value);
250                 else if (!strcmp("fog_red", key))
251                         fog_red = atof(value);
252                 else if (!strcmp("fog_green", key))
253                         fog_green = atof(value);
254                 else if (!strcmp("fog_blue", key))
255                         fog_blue = atof(value);
256         }
257 }
258
259 /*
260 =====================
261 CL_SignonReply
262
263 An svc_signonnum has been received, perform a client side setup
264 =====================
265 */
266 static void CL_SignonReply (void)
267 {
268         //char  str[8192];
269
270 Con_DPrintf("CL_SignonReply: %i\n", cls.signon);
271
272         switch (cls.signon)
273         {
274         case 1:
275                 MSG_WriteByte (&cls.message, clc_stringcmd);
276                 MSG_WriteString (&cls.message, "prespawn");
277                 break;
278
279         case 2:
280                 MSG_WriteByte (&cls.message, clc_stringcmd);
281                 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
282
283                 MSG_WriteByte (&cls.message, clc_stringcmd);
284                 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
285
286                 if (cl_pmodel.integer)
287                 {
288                         MSG_WriteByte (&cls.message, clc_stringcmd);
289                         MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
290                 }
291
292                 MSG_WriteByte (&cls.message, clc_stringcmd);
293                 MSG_WriteString (&cls.message, va("rate %i\n", cl_rate.integer));
294
295                 MSG_WriteByte (&cls.message, clc_stringcmd);
296                 MSG_WriteString (&cls.message, "spawn");
297                 break;
298
299         case 3:
300                 MSG_WriteByte (&cls.message, clc_stringcmd);
301                 MSG_WriteString (&cls.message, "begin");
302                 break;
303
304         case 4:
305                 Con_ClearNotify();
306                 break;
307         }
308 }
309
310 /*
311 ==================
312 CL_ParseServerInfo
313 ==================
314 */
315 qbyte entlife[MAX_EDICTS];
316 // FIXME: this is a lot of memory to be keeping around, this needs to be dynamically allocated and freed
317 static char parse_model_precache[MAX_MODELS][MAX_QPATH];
318 static char parse_sound_precache[MAX_SOUNDS][MAX_QPATH];
319 void CL_ParseServerInfo (void)
320 {
321         char *str;
322         int i;
323         int nummodels, numsounds;
324         entity_t *ent;
325
326         Con_DPrint("Serverinfo packet received.\n");
327 //
328 // wipe the client_state_t struct
329 //
330         CL_ClearState ();
331
332 // parse protocol version number
333         i = MSG_ReadLong ();
334         // hack for unmarked Nehahra movie demos which had a custom protocol
335         if (i == PROTOCOL_QUAKE && cls.demoplayback && demo_nehahra.integer)
336                 i = PROTOCOL_NEHAHRAMOVIE;
337         if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_NEHAHRAMOVIE)
338         {
339                 Host_Error("CL_ParseServerInfo: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_NEHAHRAMOVIE);
340                 return;
341         }
342         cl.protocol = i;
343
344 // parse maxclients
345         cl.maxclients = MSG_ReadByte ();
346         if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
347         {
348                 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
349                 return;
350         }
351         Mem_EmptyPool(cl_scores_mempool);
352         cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
353
354 // parse gametype
355         cl.gametype = MSG_ReadByte ();
356
357 // parse signon message
358         str = MSG_ReadString ();
359         strlcpy (cl.levelname, str, sizeof(cl.levelname));
360
361 // seperate the printfs so the server message can have a color
362         if (cl.protocol != PROTOCOL_NEHAHRAMOVIE) // no messages when playing the Nehahra movie
363                 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\2%s\n", str);
364
365         // check memory integrity
366         Mem_CheckSentinelsGlobal();
367
368         // disable until we get textures for it
369         R_ResetSkyBox();
370
371         memset(cl.model_precache, 0, sizeof(cl.model_precache));
372         memset(cl.sound_precache, 0, sizeof(cl.sound_precache));
373
374         // parse model precache list
375         for (nummodels=1 ; ; nummodels++)
376         {
377                 str = MSG_ReadString();
378                 if (!str[0])
379                         break;
380                 if (nummodels==MAX_MODELS)
381                         Host_Error ("Server sent too many model precaches\n");
382                 if (strlen(str) >= MAX_QPATH)
383                         Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
384                 strlcpy (parse_model_precache[nummodels], str, sizeof (parse_model_precache[nummodels]));
385         }
386         // parse sound precache list
387         for (numsounds=1 ; ; numsounds++)
388         {
389                 str = MSG_ReadString();
390                 if (!str[0])
391                         break;
392                 if (numsounds==MAX_SOUNDS)
393                         Host_Error("Server sent too many sound precaches\n");
394                 if (strlen(str) >= MAX_QPATH)
395                         Host_Error("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
396                 strlcpy (parse_sound_precache[numsounds], str, sizeof (parse_sound_precache[numsounds]));
397         }
398
399         // touch all of the precached models that are still loaded so we can free
400         // anything that isn't needed
401         Mod_ClearUsed();
402         for (i = 1;i < nummodels;i++)
403         {
404                 CL_KeepaliveMessage();
405                 Mod_TouchModel(parse_model_precache[i]);
406         }
407         Mod_PurgeUnused();
408
409         // do the same for sounds
410         S_ClearUsed();
411         for (i = 1;i < numsounds;i++)
412         {
413                 CL_KeepaliveMessage();
414                 S_TouchSound(parse_sound_precache[i]);
415         }
416         S_PurgeUnused();
417
418         // now we try to load everything that is new
419
420         // world model
421         CL_KeepaliveMessage ();
422         cl.model_precache[1] = Mod_ForName(parse_model_precache[1], false, false, true);
423         if (cl.model_precache[1] == NULL)
424                 Con_Printf("Map %s not found\n", parse_model_precache[1]);
425
426         // normal models
427         for (i=2 ; i<nummodels ; i++)
428         {
429                 CL_KeepaliveMessage();
430                 if ((cl.model_precache[i] = Mod_ForName(parse_model_precache[i], false, false, false)) == NULL)
431                         Con_Printf("Model %s not found\n", parse_model_precache[i]);
432         }
433
434         // sounds
435         for (i=1 ; i<numsounds ; i++)
436         {
437                 CL_KeepaliveMessage();
438                 cl.sound_precache[i] = S_PrecacheSound(parse_sound_precache[i], true);
439         }
440
441         // local state
442         ent = &cl_entities[0];
443         // entire entity array was cleared, so just fill in a few fields
444         ent->state_current.active = true;
445         ent->render.model = cl.worldmodel = cl.model_precache[1];
446         ent->render.scale = 1; // some of the renderer still relies on scale
447         ent->render.alpha = 1;
448         ent->render.flags = RENDER_SHADOW | RENDER_LIGHT;
449         Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
450         Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
451         CL_BoundingBoxForEntity(&ent->render);
452         // clear entlife array
453         memset(entlife, 0, MAX_EDICTS);
454
455         cl_num_entities = 1;
456
457         R_Modules_NewMap();
458         CL_CGVM_Start();
459
460         // noclip is turned off at start
461         noclip_anglehack = false;
462
463         // check memory integrity
464         Mem_CheckSentinelsGlobal();
465 }
466
467 void CL_ValidateState(entity_state_t *s)
468 {
469         model_t *model;
470
471         if (!s->active)
472                 return;
473
474         if (s->modelindex >= MAX_MODELS)
475                 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
476
477         // colormap is client index + 1
478         if (s->colormap > cl.maxclients)
479                 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
480
481         model = cl.model_precache[s->modelindex];
482         Mod_CheckLoaded(model);
483         if (model && s->frame >= model->numframes)
484         {
485                 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
486                 s->frame = 0;
487         }
488         if (model && s->skin > 0 && s->skin >= model->numskins)
489         {
490                 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
491                 s->skin = 0;
492         }
493 }
494
495 void CL_MoveLerpEntityStates(entity_t *ent)
496 {
497         float odelta[3], adelta[3];
498         VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
499         VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
500         if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
501         {
502                 // we definitely shouldn't lerp
503                 ent->persistent.lerpdeltatime = 0;
504                 ent->persistent.lerpstarttime = cl.mtime[1];
505                 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
506                 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
507                 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
508                 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
509         }
510         else if (ent->state_current.flags & RENDER_STEP)
511         {
512                 // monster interpolation
513                 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
514                 {
515                         ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
516                         ent->persistent.lerpstarttime = cl.mtime[1];
517                         VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
518                         VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
519                         VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
520                         VectorCopy(ent->state_current.angles, ent->persistent.newangles);
521                 }
522         }
523         else
524         {
525                 // not a monster
526                 ent->persistent.lerpstarttime = cl.mtime[1];
527                 // no lerp if it's singleplayer
528                 if (cl.islocalgame)
529                         ent->persistent.lerpdeltatime = 0;
530                 else
531                         ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
532                 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
533                 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
534                 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
535                 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
536         }
537 }
538
539 /*
540 ==================
541 CL_ParseUpdate
542
543 Parse an entity update message from the server
544 If an entities model or origin changes from frame to frame, it must be
545 relinked.  Other attributes can change without relinking.
546 ==================
547 */
548 void CL_ParseUpdate (int bits)
549 {
550         int num;
551         entity_t *ent;
552         entity_state_t new;
553
554         if (bits & U_MOREBITS)
555                 bits |= (MSG_ReadByte()<<8);
556         if ((bits & U_EXTEND1) && cl.protocol != PROTOCOL_NEHAHRAMOVIE)
557         {
558                 bits |= MSG_ReadByte() << 16;
559                 if (bits & U_EXTEND2)
560                         bits |= MSG_ReadByte() << 24;
561         }
562
563         if (bits & U_LONGENTITY)
564                 num = (unsigned) MSG_ReadShort ();
565         else
566                 num = (unsigned) MSG_ReadByte ();
567
568         if (num >= MAX_EDICTS)
569                 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
570         if (num < 1)
571                 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
572
573         ent = cl_entities + num;
574
575         // note: this inherits the 'active' state of the baseline chosen
576         // (state_baseline is always active, state_current may not be active if
577         // the entity was missing in the last frame)
578         if (bits & U_DELTA)
579                 new = ent->state_current;
580         else
581         {
582                 new = ent->state_baseline;
583                 new.active = true;
584         }
585
586         new.number = num;
587         new.time = cl.mtime[0];
588         new.flags = 0;
589         if (bits & U_MODEL)             new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
590         if (bits & U_FRAME)             new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
591         if (bits & U_COLORMAP)  new.colormap = MSG_ReadByte();
592         if (bits & U_SKIN)              new.skin = MSG_ReadByte();
593         if (bits & U_EFFECTS)   new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
594         if (bits & U_ORIGIN1)   new.origin[0] = MSG_ReadCoord();
595         if (bits & U_ANGLE1)    new.angles[0] = MSG_ReadAngle();
596         if (bits & U_ORIGIN2)   new.origin[1] = MSG_ReadCoord();
597         if (bits & U_ANGLE2)    new.angles[1] = MSG_ReadAngle();
598         if (bits & U_ORIGIN3)   new.origin[2] = MSG_ReadCoord();
599         if (bits & U_ANGLE3)    new.angles[2] = MSG_ReadAngle();
600         if (bits & U_STEP)              new.flags |= RENDER_STEP;
601         if (bits & U_ALPHA)             new.alpha = MSG_ReadByte();
602         if (bits & U_SCALE)             new.scale = MSG_ReadByte();
603         if (bits & U_EFFECTS2)  new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
604         if (bits & U_GLOWSIZE)  new.glowsize = MSG_ReadByte();
605         if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
606         // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
607         if (bits & U_COLORMOD)  MSG_ReadByte();
608         if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
609         if (bits & U_FRAME2)    new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
610         if (bits & U_MODEL2)    new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
611         if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
612         if (bits & U_EXTERIORMODEL)     new.flags |= RENDER_EXTERIORMODEL;
613
614         // LordHavoc: to allow playback of the Nehahra movie
615         if (cl.protocol == PROTOCOL_NEHAHRAMOVIE && (bits & U_EXTEND1))
616         {
617                 // LordHavoc: evil format
618                 int i = MSG_ReadFloat();
619                 int j = MSG_ReadFloat() * 255.0f;
620                 if (i == 2)
621                 {
622                         i = MSG_ReadFloat();
623                         if (i)
624                                 new.effects |= EF_FULLBRIGHT;
625                 }
626                 if (j < 0)
627                         new.alpha = 0;
628                 else if (j == 0 || j >= 255)
629                         new.alpha = 255;
630                 else
631                         new.alpha = j;
632         }
633
634         if (new.active)
635                 CL_ValidateState(&new);
636
637         ent->state_previous = ent->state_current;
638         ent->state_current = new;
639         if (ent->state_current.active)
640         {
641                 CL_MoveLerpEntityStates(ent);
642                 cl_entities_active[ent->state_current.number] = true;
643                 // mark as visible (no kill this frame)
644                 entlife[ent->state_current.number] = 2;
645         }
646 }
647
648 static entity_frame_t entityframe;
649 extern mempool_t *cl_entities_mempool;
650 void CL_ReadEntityFrame(void)
651 {
652         if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
653         {
654                 int i;
655                 entity_t *ent;
656                 EntityFrame_Read(&cl.entitydatabase);
657                 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
658                 for (i = 0;i < entityframe.numentities;i++)
659                 {
660                         // copy the states
661                         ent = &cl_entities[entityframe.entitydata[i].number];
662                         ent->state_previous = ent->state_current;
663                         ent->state_current = entityframe.entitydata[i];
664                         CL_MoveLerpEntityStates(ent);
665                         // the entity lives again...
666                         entlife[ent->state_current.number] = 2;
667                         cl_entities_active[ent->state_current.number] = true;
668                 }
669         }
670         else
671         {
672                 if (!cl.entitydatabase4)
673                         cl.entitydatabase4 = EntityFrame4_AllocDatabase(cl_entities_mempool);
674                 EntityFrame4_CL_ReadFrame(cl.entitydatabase4);
675         }
676 }
677
678 void CL_EntityUpdateSetup(void)
679 {
680 }
681
682 void CL_EntityUpdateEnd(void)
683 {
684         if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_NEHAHRAMOVIE || cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
685         {
686                 int i;
687                 // disable entities that disappeared this frame
688                 for (i = 1;i < MAX_EDICTS;i++)
689                 {
690                         // clear only the entities that were active last frame but not this
691                         // frame, don't waste time clearing all entities (which would cause
692                         // cache misses)
693                         if (entlife[i])
694                         {
695                                 entlife[i]--;
696                                 if (!entlife[i])
697                                         cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
698                         }
699                 }
700         }
701 }
702
703 /*
704 ==================
705 CL_ParseBaseline
706 ==================
707 */
708 void CL_ParseBaseline (entity_t *ent, int large)
709 {
710         int i;
711
712         ClearStateToDefault(&ent->state_baseline);
713         ent->state_baseline.active = true;
714         if (large)
715         {
716                 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
717                 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
718         }
719         else
720         {
721                 ent->state_baseline.modelindex = MSG_ReadByte ();
722                 ent->state_baseline.frame = MSG_ReadByte ();
723         }
724         ent->state_baseline.colormap = MSG_ReadByte();
725         ent->state_baseline.skin = MSG_ReadByte();
726         for (i = 0;i < 3;i++)
727         {
728                 ent->state_baseline.origin[i] = MSG_ReadCoord ();
729                 ent->state_baseline.angles[i] = MSG_ReadAngle ();
730         }
731         CL_ValidateState(&ent->state_baseline);
732         ent->state_previous = ent->state_current = ent->state_baseline;
733 }
734
735
736 /*
737 ==================
738 CL_ParseClientdata
739
740 Server information pertaining to this client only
741 ==================
742 */
743 void CL_ParseClientdata (int bits)
744 {
745         int i, j;
746
747         bits &= 0xFFFF;
748         if (bits & SU_EXTEND1)
749                 bits |= (MSG_ReadByte() << 16);
750         if (bits & SU_EXTEND2)
751                 bits |= (MSG_ReadByte() << 24);
752
753         if (bits & SU_VIEWHEIGHT)
754                 cl.viewheight = MSG_ReadChar ();
755         else
756                 cl.viewheight = DEFAULT_VIEWHEIGHT;
757
758         if (bits & SU_IDEALPITCH)
759                 cl.idealpitch = MSG_ReadChar ();
760         else
761                 cl.idealpitch = 0;
762
763         VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
764         if (cl.protocol == PROTOCOL_DARKPLACES5)
765         {
766                 for (i = 0;i < 3;i++)
767                 {
768                         if (bits & (SU_PUNCH1<<i) )
769                                 cl.punchangle[i] = MSG_ReadPreciseAngle();
770                         else
771                                 cl.punchangle[i] = 0;
772                         if (bits & (SU_PUNCHVEC1<<i))
773                                 cl.punchvector[i] = MSG_ReadFloat();
774                         else
775                                 cl.punchvector[i] = 0;
776                         if (bits & (SU_VELOCITY1<<i) )
777                                 cl.mvelocity[0][i] = MSG_ReadFloat();
778                         else
779                                 cl.mvelocity[0][i] = 0;
780                 }
781         }
782         else
783         {
784                 for (i = 0;i < 3;i++)
785                 {
786                         if (bits & (SU_PUNCH1<<i) )
787                         {
788                                 if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
789                                         cl.punchangle[i] = MSG_ReadPreciseAngle();
790                                 else
791                                         cl.punchangle[i] = MSG_ReadChar();
792                         }
793                         else
794                                 cl.punchangle[i] = 0;
795                         if (bits & (SU_PUNCHVEC1<<i))
796                                 cl.punchvector[i] = MSG_ReadCoord();
797                         else
798                                 cl.punchvector[i] = 0;
799                         if (bits & (SU_VELOCITY1<<i) )
800                                 cl.mvelocity[0][i] = MSG_ReadChar()*16;
801                         else
802                                 cl.mvelocity[0][i] = 0;
803                 }
804         }
805
806         i = MSG_ReadLong ();
807         if (cl.items != i)
808         {       // set flash times
809                 for (j=0 ; j<32 ; j++)
810                         if ( (i & (1<<j)) && !(cl.items & (1<<j)))
811                                 cl.item_gettime[j] = cl.time;
812                 cl.items = i;
813         }
814
815         cl.onground = (bits & SU_ONGROUND) != 0;
816         cl.inwater = (bits & SU_INWATER) != 0;
817
818         cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
819         cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
820         cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
821         cl.stats[STAT_HEALTH] = MSG_ReadShort();
822         cl.stats[STAT_AMMO] = MSG_ReadByte();
823
824         cl.stats[STAT_SHELLS] = MSG_ReadByte();
825         cl.stats[STAT_NAILS] = MSG_ReadByte();
826         cl.stats[STAT_ROCKETS] = MSG_ReadByte();
827         cl.stats[STAT_CELLS] = MSG_ReadByte();
828
829         i = MSG_ReadByte ();
830
831         if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
832                 i = (1<<i);
833         // GAME_NEXUIZ hud needs weapon change time
834         // GAME_NEXUIZ uses a bit number as it's STAT_ACTIVEWEAPON, not a bitfield
835         // like other modes
836         if (cl.stats[STAT_ACTIVEWEAPON] != i)
837                 cl.weapontime = cl.time;
838         cl.stats[STAT_ACTIVEWEAPON] = i;
839
840         cl.viewzoomold = cl.viewzoomnew; // for interpolation
841         if (bits & SU_VIEWZOOM)
842         {
843                 i = MSG_ReadByte();
844                 if (i < 2)
845                         i = 2;
846                 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
847         }
848         else
849                 cl.viewzoomnew = 1;
850
851 }
852
853 /*
854 =====================
855 CL_ParseStatic
856 =====================
857 */
858 void CL_ParseStatic (int large)
859 {
860         entity_t *ent;
861
862         if (cl_num_static_entities >= cl_max_static_entities)
863                 Host_Error ("Too many static entities");
864         ent = &cl_static_entities[cl_num_static_entities++];
865         CL_ParseBaseline (ent, large);
866
867 // copy it to the current state
868         ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
869         ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
870         ent->render.framelerp = 0;
871         // make torchs play out of sync
872         ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
873         ent->render.colormap = -1; // no special coloring
874         ent->render.skinnum = ent->state_baseline.skin;
875         ent->render.effects = ent->state_baseline.effects;
876         ent->render.alpha = 1;
877         //ent->render.scale = 1;
878
879         //VectorCopy (ent->state_baseline.origin, ent->render.origin);
880         //VectorCopy (ent->state_baseline.angles, ent->render.angles);
881
882         Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, ent->state_baseline.origin[0], ent->state_baseline.origin[1], ent->state_baseline.origin[2], ent->state_baseline.angles[0], ent->state_baseline.angles[1], ent->state_baseline.angles[2], 1);
883         Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
884         CL_BoundingBoxForEntity(&ent->render);
885
886         // This is definitely cheating...
887         if (ent->render.model == NULL)
888                 cl_num_static_entities--;
889 }
890
891 /*
892 ===================
893 CL_ParseStaticSound
894 ===================
895 */
896 void CL_ParseStaticSound (int large)
897 {
898         vec3_t          org;
899         int                     sound_num, vol, atten;
900
901         MSG_ReadVector(org);
902         if (large)
903                 sound_num = (unsigned short) MSG_ReadShort ();
904         else
905                 sound_num = MSG_ReadByte ();
906         vol = MSG_ReadByte ();
907         atten = MSG_ReadByte ();
908
909         S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
910 }
911
912 void CL_ParseEffect (void)
913 {
914         vec3_t          org;
915         int                     modelindex, startframe, framecount, framerate;
916
917         MSG_ReadVector(org);
918         modelindex = MSG_ReadByte ();
919         startframe = MSG_ReadByte ();
920         framecount = MSG_ReadByte ();
921         framerate = MSG_ReadByte ();
922
923         CL_Effect(org, modelindex, startframe, framecount, framerate);
924 }
925
926 void CL_ParseEffect2 (void)
927 {
928         vec3_t          org;
929         int                     modelindex, startframe, framecount, framerate;
930
931         MSG_ReadVector(org);
932         modelindex = MSG_ReadShort ();
933         startframe = MSG_ReadShort ();
934         framecount = MSG_ReadByte ();
935         framerate = MSG_ReadByte ();
936
937         CL_Effect(org, modelindex, startframe, framecount, framerate);
938 }
939
940 model_t *cl_model_bolt = NULL;
941 model_t *cl_model_bolt2 = NULL;
942 model_t *cl_model_bolt3 = NULL;
943 model_t *cl_model_beam = NULL;
944
945 sfx_t *cl_sfx_wizhit;
946 sfx_t *cl_sfx_knighthit;
947 sfx_t *cl_sfx_tink1;
948 sfx_t *cl_sfx_ric1;
949 sfx_t *cl_sfx_ric2;
950 sfx_t *cl_sfx_ric3;
951 sfx_t *cl_sfx_r_exp3;
952
953 /*
954 =================
955 CL_ParseTEnt
956 =================
957 */
958 void CL_InitTEnts (void)
959 {
960         cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
961         cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
962         cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
963         cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
964         cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
965         cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
966         cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
967 }
968
969 void CL_ParseBeam (model_t *m, int lightning)
970 {
971         int i, ent;
972         vec3_t start, end;
973         beam_t *b;
974
975         ent = MSG_ReadShort ();
976         MSG_ReadVector(start);
977         MSG_ReadVector(end);
978
979         if (ent >= MAX_EDICTS)
980         {
981                 Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
982                 ent = 0;
983         }
984
985         // override any beam with the same entity
986         for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
987         {
988                 if (b->entity == ent)
989                 {
990                         //b->entity = ent;
991                         b->lightning = lightning;
992                         b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
993                         b->model = m;
994                         b->endtime = cl.time + 0.2;
995                         VectorCopy (start, b->start);
996                         VectorCopy (end, b->end);
997                         return;
998                 }
999         }
1000
1001         // find a free beam
1002         for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
1003         {
1004                 if (!b->model || b->endtime < cl.time)
1005                 {
1006                         b->entity = ent;
1007                         b->lightning = lightning;
1008                         b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
1009                         b->model = m;
1010                         b->endtime = cl.time + 0.2;
1011                         VectorCopy (start, b->start);
1012                         VectorCopy (end, b->end);
1013                         return;
1014                 }
1015         }
1016         Con_Print("beam list overflow!\n");
1017 }
1018
1019 void CL_ParseTempEntity(void)
1020 {
1021         int type;
1022         vec3_t pos;
1023         vec3_t dir;
1024         vec3_t pos2;
1025         vec3_t color;
1026         int rnd;
1027         int colorStart, colorLength, count;
1028         float velspeed, radius;
1029         qbyte *tempcolor;
1030         matrix4x4_t tempmatrix;
1031
1032         type = MSG_ReadByte();
1033         switch (type)
1034         {
1035         case TE_WIZSPIKE:
1036                 // spike hitting wall
1037                 MSG_ReadVector(pos);
1038                 CL_FindNonSolidLocation(pos, pos, 4);
1039                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1040                 CL_AllocDlight(NULL, &tempmatrix, 100, 0.12f, 0.50f, 0.12f, 500, 0.2, 0, 0, false, 1);
1041                 CL_RunParticleEffect(pos, vec3_origin, 20, 30);
1042                 S_StartSound(-1, 0, cl_sfx_wizhit, pos, 1, 1);
1043                 break;
1044
1045         case TE_KNIGHTSPIKE:
1046                 // spike hitting wall
1047                 MSG_ReadVector(pos);
1048                 CL_FindNonSolidLocation(pos, pos, 4);
1049                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1050                 CL_AllocDlight(NULL, &tempmatrix, 100, 0.50f, 0.30f, 0.10f, 500, 0.2, 0, 0, false, 1);
1051                 CL_RunParticleEffect(pos, vec3_origin, 226, 20);
1052                 S_StartSound(-1, 0, cl_sfx_knighthit, pos, 1, 1);
1053                 break;
1054
1055         case TE_SPIKE:
1056                 // spike hitting wall
1057                 MSG_ReadVector(pos);
1058                 CL_FindNonSolidLocation(pos, pos, 4);
1059                 // LordHavoc: changed to spark shower
1060                 CL_SparkShower(pos, vec3_origin, 15);
1061                 if (rand() % 5)
1062                         S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1063                 else
1064                 {
1065                         rnd = rand() & 3;
1066                         if (rnd == 1)
1067                                 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1068                         else if (rnd == 2)
1069                                 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1070                         else
1071                                 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1072                 }
1073                 break;
1074         case TE_SPIKEQUAD:
1075                 // quad spike hitting wall
1076                 MSG_ReadVector(pos);
1077                 CL_FindNonSolidLocation(pos, pos, 4);
1078                 // LordHavoc: changed to spark shower
1079                 CL_SparkShower(pos, vec3_origin, 15);
1080                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1081                 CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, 0, true, 1);
1082                 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1083                 if (rand() % 5)
1084                         S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1085                 else
1086                 {
1087                         rnd = rand() & 3;
1088                         if (rnd == 1)
1089                                 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1090                         else if (rnd == 2)
1091                                 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1092                         else
1093                                 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1094                 }
1095                 break;
1096         case TE_SUPERSPIKE:
1097                 // super spike hitting wall
1098                 MSG_ReadVector(pos);
1099                 CL_FindNonSolidLocation(pos, pos, 4);
1100                 // LordHavoc: changed to dust shower
1101                 CL_SparkShower(pos, vec3_origin, 30);
1102                 if (rand() % 5)
1103                         S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1104                 else
1105                 {
1106                         rnd = rand() & 3;
1107                         if (rnd == 1)
1108                                 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1109                         else if (rnd == 2)
1110                                 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1111                         else
1112                                 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1113                 }
1114                 break;
1115         case TE_SUPERSPIKEQUAD:
1116                 // quad super spike hitting wall
1117                 MSG_ReadVector(pos);
1118                 CL_FindNonSolidLocation(pos, pos, 4);
1119                 // LordHavoc: changed to dust shower
1120                 CL_SparkShower(pos, vec3_origin, 30);
1121                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1122                 CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, 0, true, 1);
1123                 if (rand() % 5)
1124                         S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1125                 else
1126                 {
1127                         rnd = rand() & 3;
1128                         if (rnd == 1)
1129                                 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1130                         else if (rnd == 2)
1131                                 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1132                         else
1133                                 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1134                 }
1135                 break;
1136                 // LordHavoc: added for improved blood splatters
1137         case TE_BLOOD:
1138                 // blood puff
1139                 MSG_ReadVector(pos);
1140                 CL_FindNonSolidLocation(pos, pos, 4);
1141                 dir[0] = MSG_ReadChar();
1142                 dir[1] = MSG_ReadChar();
1143                 dir[2] = MSG_ReadChar();
1144                 count = MSG_ReadByte();
1145                 CL_BloodPuff(pos, dir, count);
1146                 break;
1147         case TE_SPARK:
1148                 // spark shower
1149                 MSG_ReadVector(pos);
1150                 CL_FindNonSolidLocation(pos, pos, 4);
1151                 dir[0] = MSG_ReadChar();
1152                 dir[1] = MSG_ReadChar();
1153                 dir[2] = MSG_ReadChar();
1154                 count = MSG_ReadByte();
1155                 CL_SparkShower(pos, dir, count);
1156                 break;
1157         case TE_PLASMABURN:
1158                 MSG_ReadVector(pos);
1159                 CL_FindNonSolidLocation(pos, pos, 4);
1160                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1161                 CL_AllocDlight(NULL, &tempmatrix, 200, 1, 1, 1, 1000, 0.2, 0, 0, true, 1);
1162                 CL_PlasmaBurn(pos);
1163                 break;
1164                 // LordHavoc: added for improved gore
1165         case TE_BLOODSHOWER:
1166                 // vaporized body
1167                 MSG_ReadVector(pos); // mins
1168                 MSG_ReadVector(pos2); // maxs
1169                 velspeed = MSG_ReadCoord(); // speed
1170                 count = MSG_ReadShort(); // number of particles
1171                 CL_BloodShower(pos, pos2, velspeed, count);
1172                 break;
1173         case TE_PARTICLECUBE:
1174                 // general purpose particle effect
1175                 MSG_ReadVector(pos); // mins
1176                 MSG_ReadVector(pos2); // maxs
1177                 MSG_ReadVector(dir); // dir
1178                 count = MSG_ReadShort(); // number of particles
1179                 colorStart = MSG_ReadByte(); // color
1180                 colorLength = MSG_ReadByte(); // gravity (1 or 0)
1181                 velspeed = MSG_ReadCoord(); // randomvel
1182                 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1183                 break;
1184
1185         case TE_PARTICLERAIN:
1186                 // general purpose particle effect
1187                 MSG_ReadVector(pos); // mins
1188                 MSG_ReadVector(pos2); // maxs
1189                 MSG_ReadVector(dir); // dir
1190                 count = MSG_ReadShort(); // number of particles
1191                 colorStart = MSG_ReadByte(); // color
1192                 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1193                 break;
1194
1195         case TE_PARTICLESNOW:
1196                 // general purpose particle effect
1197                 MSG_ReadVector(pos); // mins
1198                 MSG_ReadVector(pos2); // maxs
1199                 MSG_ReadVector(dir); // dir
1200                 count = MSG_ReadShort(); // number of particles
1201                 colorStart = MSG_ReadByte(); // color
1202                 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1203                 break;
1204
1205         case TE_GUNSHOT:
1206                 // bullet hitting wall
1207                 MSG_ReadVector(pos);
1208                 CL_FindNonSolidLocation(pos, pos, 4);
1209                 // LordHavoc: changed to dust shower
1210                 CL_SparkShower(pos, vec3_origin, 15);
1211                 break;
1212
1213         case TE_GUNSHOTQUAD:
1214                 // quad bullet hitting wall
1215                 MSG_ReadVector(pos);
1216                 CL_FindNonSolidLocation(pos, pos, 4);
1217                 CL_SparkShower(pos, vec3_origin, 15);
1218                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1219                 CL_AllocDlight(NULL, &tempmatrix, 100, 0.15f, 0.15f, 1.5f, 500, 0.2, 0, 0, true, 1);
1220                 break;
1221
1222         case TE_EXPLOSION:
1223                 // rocket explosion
1224                 MSG_ReadVector(pos);
1225                 CL_FindNonSolidLocation(pos, pos, 10);
1226                 CL_ParticleExplosion(pos);
1227                 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1228                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1229                 CL_AllocDlight(NULL, &tempmatrix, 350, 2.5f, 2.0f, 1.0f, 700, 0.5, 0, 0, true, 1);
1230                 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1231                 break;
1232
1233         case TE_EXPLOSIONQUAD:
1234                 // quad rocket explosion
1235                 MSG_ReadVector(pos);
1236                 CL_FindNonSolidLocation(pos, pos, 10);
1237                 CL_ParticleExplosion(pos);
1238                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1239                 CL_AllocDlight(NULL, &tempmatrix, 350, 2.5f, 2.0f, 4.0f, 700, 0.5, 0, 0, true, 1);
1240                 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1241                 break;
1242
1243         case TE_EXPLOSION3:
1244                 // Nehahra movie colored lighting explosion
1245                 MSG_ReadVector(pos);
1246                 CL_FindNonSolidLocation(pos, pos, 10);
1247                 CL_ParticleExplosion(pos);
1248                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1249                 color[0] = MSG_ReadCoord() * (2.0f / 1.0f);
1250                 color[1] = MSG_ReadCoord() * (2.0f / 1.0f);
1251                 color[2] = MSG_ReadCoord() * (2.0f / 1.0f);
1252                 CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, 0, true, 1);  
1253                 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1254                 break;
1255
1256         case TE_EXPLOSIONRGB:
1257                 // colored lighting explosion
1258                 MSG_ReadVector(pos);
1259                 CL_FindNonSolidLocation(pos, pos, 10);
1260                 CL_ParticleExplosion(pos);
1261                 color[0] = MSG_ReadByte() * (2.0f / 255.0f);
1262                 color[1] = MSG_ReadByte() * (2.0f / 255.0f);
1263                 color[2] = MSG_ReadByte() * (2.0f / 255.0f);
1264                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1265                 CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, 0, true, 1);
1266                 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1267                 break;
1268
1269         case TE_TAREXPLOSION:
1270                 // tarbaby explosion
1271                 MSG_ReadVector(pos);
1272                 CL_FindNonSolidLocation(pos, pos, 10);
1273                 CL_BlobExplosion(pos);
1274
1275                 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1276                 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1277                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1278                 CL_AllocDlight(NULL, &tempmatrix, 600, 1.6f, 0.8f, 2.0f, 1200, 0.5, 0, 0, true, 1);
1279                 break;
1280
1281         case TE_SMALLFLASH:
1282                 MSG_ReadVector(pos);
1283                 CL_FindNonSolidLocation(pos, pos, 10);
1284                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1285                 CL_AllocDlight(NULL, &tempmatrix, 200, 2, 2, 2, 1000, 0.2, 0, 0, true, 1);
1286                 break;
1287
1288         case TE_CUSTOMFLASH:
1289                 MSG_ReadVector(pos);
1290                 CL_FindNonSolidLocation(pos, pos, 4);
1291                 radius = MSG_ReadByte() * 8;
1292                 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1293                 color[0] = MSG_ReadByte() * (2.0f / 255.0f);
1294                 color[1] = MSG_ReadByte() * (2.0f / 255.0f);
1295                 color[2] = MSG_ReadByte() * (2.0f / 255.0f);
1296                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1297                 CL_AllocDlight(NULL, &tempmatrix, radius, color[0], color[1], color[2], radius / velspeed, velspeed, 0, 0, true, 1);
1298                 break;
1299
1300         case TE_FLAMEJET:
1301                 MSG_ReadVector(pos);
1302                 MSG_ReadVector(dir);
1303                 count = MSG_ReadByte();
1304                 CL_Flames(pos, dir, count);
1305                 break;
1306
1307         case TE_LIGHTNING1:
1308                 // lightning bolts
1309                 if (!cl_model_bolt)
1310                         cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1311                 CL_ParseBeam(cl_model_bolt, true);
1312                 break;
1313
1314         case TE_LIGHTNING2:
1315                 // lightning bolts
1316                 if (!cl_model_bolt2)
1317                         cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1318                 CL_ParseBeam(cl_model_bolt2, true);
1319                 break;
1320
1321         case TE_LIGHTNING3:
1322                 // lightning bolts
1323                 if (!cl_model_bolt3)
1324                         cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1325                 CL_ParseBeam(cl_model_bolt3, false);
1326                 break;
1327
1328 // PGM 01/21/97
1329         case TE_BEAM:
1330                 // grappling hook beam
1331                 if (!cl_model_beam)
1332                         cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1333                 CL_ParseBeam(cl_model_beam, false);
1334                 break;
1335 // PGM 01/21/97
1336
1337 // LordHavoc: for compatibility with the Nehahra movie...
1338         case TE_LIGHTNING4NEH:
1339                 CL_ParseBeam(Mod_ForName(MSG_ReadString(), true, false, false), false);
1340                 break;
1341
1342         case TE_LAVASPLASH:
1343                 MSG_ReadVector(pos);
1344                 CL_LavaSplash(pos);
1345                 break;
1346
1347         case TE_TELEPORT:
1348                 MSG_ReadVector(pos);
1349                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1350                 CL_AllocDlight(NULL, &tempmatrix, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f, 0, 0, true, 1);
1351 //              CL_TeleportSplash(pos);
1352                 break;
1353
1354         case TE_EXPLOSION2:
1355                 // color mapped explosion
1356                 MSG_ReadVector(pos);
1357                 CL_FindNonSolidLocation(pos, pos, 10);
1358                 colorStart = MSG_ReadByte();
1359                 colorLength = MSG_ReadByte();
1360                 CL_ParticleExplosion2(pos, colorStart, colorLength);
1361                 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1362                 color[0] = tempcolor[0] * (2.0f / 255.0f);
1363                 color[1] = tempcolor[1] * (2.0f / 255.0f);
1364                 color[2] = tempcolor[2] * (2.0f / 255.0f);
1365                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1366                 CL_AllocDlight(NULL, &tempmatrix, 350, color[0], color[1], color[2], 700, 0.5, 0, 0, true, 1);
1367                 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1368                 break;
1369
1370         case TE_TEI_G3:
1371                 MSG_ReadVector(pos);
1372                 MSG_ReadVector(pos2);
1373                 MSG_ReadVector(dir);
1374                 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1375                 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1376                 break;
1377
1378         case TE_TEI_SMOKE:
1379                 MSG_ReadVector(pos);
1380                 MSG_ReadVector(dir);
1381                 count = MSG_ReadByte();
1382                 CL_FindNonSolidLocation(pos, pos, 4);
1383                 CL_Tei_Smoke(pos, dir, count);
1384                 break;
1385
1386         case TE_TEI_BIGEXPLOSION:
1387                 MSG_ReadVector(pos);
1388                 CL_FindNonSolidLocation(pos, pos, 10);
1389                 CL_ParticleExplosion(pos);
1390                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1391                 CL_AllocDlight(NULL, &tempmatrix, 500, 2.5f, 2.0f, 1.0f, 500, 9999, 0, 0, true, 1);
1392                 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1393                 break;
1394
1395         case TE_TEI_PLASMAHIT:
1396                 MSG_ReadVector(pos);
1397                 MSG_ReadVector(dir);
1398                 count = MSG_ReadByte();
1399                 CL_FindNonSolidLocation(pos, pos, 5);
1400                 CL_Tei_PlasmaHit(pos, dir, count);
1401                 Matrix4x4_CreateTranslate(&tempmatrix, pos[0], pos[1], pos[2]);
1402                 CL_AllocDlight(NULL, &tempmatrix, 500, 0.6, 1.2, 2.0f, 2000, 9999, 0, 0, true, 1);
1403                 break;
1404
1405         default:
1406                 Host_Error("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1407         }
1408 }
1409
1410 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf("%3i:%s\n", msg_readcount-1, x);
1411
1412 static qbyte cgamenetbuffer[65536];
1413
1414 /*
1415 =====================
1416 CL_ParseServerMessage
1417 =====================
1418 */
1419 int parsingerror = false;
1420 void CL_ParseServerMessage(void)
1421 {
1422         int                     cmd;
1423         int                     i, entitiesupdated;
1424         qbyte           cmdlog[32];
1425         char            *cmdlogname[32], *temp;
1426         int                     cmdindex, cmdcount = 0;
1427
1428         if (cls.demorecording)
1429                 CL_WriteDemoMessage ();
1430
1431         cl.last_received_message = realtime;
1432
1433 //
1434 // if recording demos, copy the message out
1435 //
1436         if (cl_shownet.integer == 1)
1437                 Con_Printf("%f %i\n", realtime, net_message.cursize);
1438         else if (cl_shownet.integer == 2)
1439                 Con_Print("------------------\n");
1440
1441         cl.onground = false;    // unless the server says otherwise
1442 //
1443 // parse the message
1444 //
1445         //MSG_BeginReading ();
1446
1447         entitiesupdated = false;
1448
1449         parsingerror = true;
1450
1451         while (1)
1452         {
1453                 if (msg_badread)
1454                         Host_Error ("CL_ParseServerMessage: Bad server message");
1455
1456                 cmd = MSG_ReadByte ();
1457
1458                 if (cmd == -1)
1459                 {
1460                         SHOWNET("END OF MESSAGE");
1461                         break;          // end of message
1462                 }
1463
1464                 cmdindex = cmdcount & 31;
1465                 cmdcount++;
1466                 cmdlog[cmdindex] = cmd;
1467
1468                 // if the high bit of the command byte is set, it is a fast update
1469                 if (cmd & 128)
1470                 {
1471                         // 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)
1472                         temp = "entity";
1473                         cmdlogname[cmdindex] = temp;
1474                         SHOWNET("fast update");
1475                         if (cls.signon == SIGNONS - 1)
1476                         {
1477                                 // first update is the final signon stage
1478                                 cls.signon = SIGNONS;
1479                                 CL_SignonReply ();
1480                         }
1481                         CL_ParseUpdate (cmd&127);
1482                         continue;
1483                 }
1484
1485                 SHOWNET(svc_strings[cmd]);
1486                 cmdlogname[cmdindex] = svc_strings[cmd];
1487                 if (!cmdlogname[cmdindex])
1488                 {
1489                         // 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)
1490                         temp = "<unknown>";
1491                         cmdlogname[cmdindex] = temp;
1492                 }
1493
1494                 // other commands
1495                 switch (cmd)
1496                 {
1497                 default:
1498                         {
1499                                 char description[32*64], temp[64];
1500                                 int count;
1501                                 strcpy (description, "packet dump: ");
1502                                 i = cmdcount - 32;
1503                                 if (i < 0)
1504                                         i = 0;
1505                                 count = cmdcount - i;
1506                                 i &= 31;
1507                                 while(count > 0)
1508                                 {
1509                                         snprintf (temp, sizeof (temp), "%3i:%s ", cmdlog[i], cmdlogname[i]);
1510                                         strlcat (description, temp, sizeof (description));
1511                                         count--;
1512                                         i++;
1513                                         i &= 31;
1514                                 }
1515                                 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1516                                 Con_Print(description);
1517                                 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1518                         }
1519                         break;
1520
1521                 case svc_nop:
1522                         if (cls.signon < SIGNONS)
1523                                 Con_Print("<-- server to client keepalive\n");
1524                         break;
1525
1526                 case svc_time:
1527                         if (!entitiesupdated)
1528                         {
1529                                 // this is a new frame, we'll be seeing entities,
1530                                 // so prepare for entity updates
1531                                 CL_EntityUpdateSetup();
1532                                 entitiesupdated = true;
1533                         }
1534                         cl.mtime[1] = cl.mtime[0];
1535                         cl.mtime[0] = MSG_ReadFloat ();
1536                         break;
1537
1538                 case svc_clientdata:
1539                         i = MSG_ReadShort ();
1540                         CL_ParseClientdata (i);
1541                         break;
1542
1543                 case svc_version:
1544                         i = MSG_ReadLong ();
1545                         // hack for unmarked Nehahra movie demos which had a custom protocol
1546                         if (i == PROTOCOL_QUAKE && cls.demoplayback && demo_nehahra.integer)
1547                                 i = PROTOCOL_NEHAHRAMOVIE;
1548                         if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_NEHAHRAMOVIE)
1549                                 Host_Error("CL_ParseServerMessage: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_NEHAHRAMOVIE);
1550                         cl.protocol = i;
1551                         break;
1552
1553                 case svc_disconnect:
1554                         Host_EndGame ("Server disconnected\n");
1555
1556                 case svc_print:
1557                         Con_Print(MSG_ReadString());
1558                         break;
1559
1560                 case svc_centerprint:
1561                         SCR_CenterPrint(MSG_ReadString ());
1562                         break;
1563
1564                 case svc_stufftext:
1565                         Cbuf_AddText (MSG_ReadString ());
1566                         break;
1567
1568                 case svc_damage:
1569                         V_ParseDamage ();
1570                         break;
1571
1572                 case svc_serverinfo:
1573                         CL_ParseServerInfo ();
1574                         break;
1575
1576                 case svc_setangle:
1577                         for (i=0 ; i<3 ; i++)
1578                                 cl.viewangles[i] = MSG_ReadAngle ();
1579                         break;
1580
1581                 case svc_setview:
1582                         cl.viewentity = (unsigned short)MSG_ReadShort ();
1583                         if (cl.viewentity >= MAX_EDICTS)
1584                                 Host_Error("svc_setview >= MAX_EDICTS\n");
1585                         // LordHavoc: assume first setview recieved is the real player entity
1586                         if (!cl.playerentity)
1587                                 cl.playerentity = cl.viewentity;
1588                         break;
1589
1590                 case svc_lightstyle:
1591                         i = MSG_ReadByte ();
1592                         if (i >= MAX_LIGHTSTYLES)
1593                                 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1594                         strlcpy (cl_lightstyle[i].map,  MSG_ReadString(), sizeof (cl_lightstyle[i].map));
1595                         cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1596                         cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1597                         break;
1598
1599                 case svc_sound:
1600                         CL_ParseStartSoundPacket(false);
1601                         break;
1602
1603                 case svc_sound2:
1604                         CL_ParseStartSoundPacket(true);
1605                         break;
1606
1607                 case svc_stopsound:
1608                         i = MSG_ReadShort();
1609                         S_StopSound(i>>3, i&7);
1610                         break;
1611
1612                 case svc_updatename:
1613                         i = MSG_ReadByte ();
1614                         if (i >= cl.maxclients)
1615                                 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1616                         strlcpy (cl.scores[i].name, MSG_ReadString (), sizeof (cl.scores[i].name));
1617                         break;
1618
1619                 case svc_updatefrags:
1620                         i = MSG_ReadByte ();
1621                         if (i >= cl.maxclients)
1622                                 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1623                         cl.scores[i].frags = MSG_ReadShort ();
1624                         break;
1625
1626                 case svc_updatecolors:
1627                         i = MSG_ReadByte ();
1628                         if (i >= cl.maxclients)
1629                                 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1630                         cl.scores[i].colors = MSG_ReadByte ();
1631                         break;
1632
1633                 case svc_particle:
1634                         CL_ParseParticleEffect ();
1635                         break;
1636
1637                 case svc_effect:
1638                         CL_ParseEffect ();
1639                         break;
1640
1641                 case svc_effect2:
1642                         CL_ParseEffect2 ();
1643                         break;
1644
1645                 case svc_spawnbaseline:
1646                         i = MSG_ReadShort ();
1647                         if (i < 0 || i >= MAX_EDICTS)
1648                                 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1649                         CL_ParseBaseline (cl_entities + i, false);
1650                         break;
1651                 case svc_spawnbaseline2:
1652                         i = MSG_ReadShort ();
1653                         if (i < 0 || i >= MAX_EDICTS)
1654                                 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1655                         CL_ParseBaseline (cl_entities + i, true);
1656                         break;
1657                 case svc_spawnstatic:
1658                         CL_ParseStatic (false);
1659                         break;
1660                 case svc_spawnstatic2:
1661                         CL_ParseStatic (true);
1662                         break;
1663                 case svc_temp_entity:
1664                         CL_ParseTempEntity ();
1665                         break;
1666
1667                 case svc_setpause:
1668                         cl.paused = MSG_ReadByte ();
1669                         if (cl.paused)
1670                         {
1671                                 CDAudio_Pause ();
1672                                 S_PauseGameSounds ();
1673                         }
1674                         else
1675                         {
1676                                 CDAudio_Resume ();
1677                                 S_ResumeGameSounds ();
1678                         }
1679                         break;
1680
1681                 case svc_signonnum:
1682                         i = MSG_ReadByte ();
1683                         if (i <= cls.signon)
1684                                 Host_Error ("Received signon %i when at %i", i, cls.signon);
1685                         cls.signon = i;
1686                         CL_SignonReply ();
1687                         break;
1688
1689                 case svc_killedmonster:
1690                         cl.stats[STAT_MONSTERS]++;
1691                         break;
1692
1693                 case svc_foundsecret:
1694                         cl.stats[STAT_SECRETS]++;
1695                         break;
1696
1697                 case svc_updatestat:
1698                         i = MSG_ReadByte ();
1699                         if (i < 0 || i >= MAX_CL_STATS)
1700                                 Host_Error ("svc_updatestat: %i is invalid", i);
1701                         cl.stats[i] = MSG_ReadLong ();
1702                         break;
1703
1704                 case svc_spawnstaticsound:
1705                         CL_ParseStaticSound (false);
1706                         break;
1707
1708                 case svc_spawnstaticsound2:
1709                         CL_ParseStaticSound (true);
1710                         break;
1711
1712                 case svc_cdtrack:
1713                         cl.cdtrack = MSG_ReadByte ();
1714                         cl.looptrack = MSG_ReadByte ();
1715                         if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1716                                 CDAudio_Play ((qbyte)cls.forcetrack, true);
1717                         else
1718                                 CDAudio_Play ((qbyte)cl.cdtrack, true);
1719                         break;
1720
1721                 case svc_intermission:
1722                         cl.intermission = 1;
1723                         cl.completed_time = cl.time;
1724                         break;
1725
1726                 case svc_finale:
1727                         cl.intermission = 2;
1728                         cl.completed_time = cl.time;
1729                         SCR_CenterPrint(MSG_ReadString ());
1730                         break;
1731
1732                 case svc_cutscene:
1733                         cl.intermission = 3;
1734                         cl.completed_time = cl.time;
1735                         SCR_CenterPrint(MSG_ReadString ());
1736                         break;
1737
1738                 case svc_sellscreen:
1739                         Cmd_ExecuteString ("help", src_command);
1740                         break;
1741                 case svc_hidelmp:
1742                         if (gamemode == GAME_TENEBRAE)
1743                         {
1744                                 // repeating particle effect
1745                                 MSG_ReadCoord();
1746                                 MSG_ReadCoord();
1747                                 MSG_ReadCoord();
1748                                 MSG_ReadCoord();
1749                                 MSG_ReadCoord();
1750                                 MSG_ReadCoord();
1751                                 MSG_ReadByte();
1752                                 MSG_ReadLong();
1753                                 MSG_ReadLong();
1754                                 MSG_ReadString();
1755                         }
1756                         else
1757                                 SHOWLMP_decodehide();
1758                         break;
1759                 case svc_showlmp:
1760                         if (gamemode == GAME_TENEBRAE)
1761                         {
1762                                 // particle effect
1763                                 MSG_ReadCoord();
1764                                 MSG_ReadCoord();
1765                                 MSG_ReadCoord();
1766                                 MSG_ReadByte();
1767                                 MSG_ReadString();
1768                         }
1769                         else
1770                                 SHOWLMP_decodeshow();
1771                         break;
1772                 case svc_skybox:
1773                         R_SetSkyBox(MSG_ReadString());
1774                         break;
1775                 case svc_cgame:
1776                         {
1777                                 int length;
1778                                 length = (int) ((unsigned short) MSG_ReadShort());
1779                                 for (i = 0;i < length;i++)
1780                                         cgamenetbuffer[i] = MSG_ReadByte();
1781                                 if (!msg_badread)
1782                                         CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1783                         }
1784                         break;
1785                 case svc_entities:
1786                         if (cls.signon == SIGNONS - 1)
1787                         {
1788                                 // first update is the final signon stage
1789                                 cls.signon = SIGNONS;
1790                                 CL_SignonReply ();
1791                         }
1792                         CL_ReadEntityFrame();
1793                         break;
1794                 }
1795         }
1796
1797         if (entitiesupdated)
1798                 CL_EntityUpdateEnd();
1799
1800         parsingerror = false;
1801 }
1802
1803 void CL_Parse_DumpPacket(void)
1804 {
1805         if (!parsingerror)
1806                 return;
1807         Con_Print("Packet dump:\n");
1808         SZ_HexDumpToConsole(&net_message);
1809         parsingerror = false;
1810 }
1811
1812 void CL_Parse_Init(void)
1813 {
1814         // LordHavoc: added demo_nehahra cvar
1815         cl_scores_mempool = Mem_AllocPool("client player info");
1816         Cvar_RegisterVariable (&demo_nehahra);
1817         if (gamemode == GAME_NEHAHRA)
1818                 Cvar_SetValue("demo_nehahra", 1);
1819         Cvar_RegisterVariable(&developer_networkentities);
1820 }