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