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