2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
20 // cl_parse.c -- parse a message received from the server
24 char *svc_strings[128] =
30 "svc_version", // [long] server version
31 "svc_setview", // [short] entity number
32 "svc_sound", // <see code>
33 "svc_time", // [float] server time
34 "svc_print", // [string] null terminated string
35 "svc_stufftext", // [string] stuffed into client's console buffer
36 // the string should be \n terminated
37 "svc_setangle", // [vec3] set the view angle to this absolute value
39 "svc_serverinfo", // [long] version
40 // [string] signon string
41 // [string]..[0]model cache [string]...[0]sounds cache
42 // [string]..[0]item cache
43 "svc_lightstyle", // [byte] [string]
44 "svc_updatename", // [byte] [string]
45 "svc_updatefrags", // [byte] [short]
46 "svc_clientdata", // <shortbits + data>
47 "svc_stopsound", // <see code>
48 "svc_updatecolors", // [byte] [byte]
49 "svc_particle", // [vec3] <variable>
50 "svc_damage", // [byte] impact [byte] blood [vec3] from
53 "OBSOLETE svc_spawnbinary",
56 "svc_temp_entity", // <variable>
62 "svc_spawnstaticsound",
64 "svc_finale", // [string] music [string] text
65 "svc_cdtrack", // [byte] track [byte] looptrack
68 "svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y
69 "svc_hidelmp", // [string] iconlabel
70 "svc_skybox", // [string] skyname
83 "svc_cgame", // 50 // [short] length [bytes] data
84 "svc_unusedlh1", // 51 // unused
85 "svc_effect", // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
86 "svc_effect2", // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
87 "svc_sound2", // 54 // short soundindex instead of byte
88 "svc_spawnbaseline2", // 55 // short modelindex instead of byte
89 "svc_spawnstatic2", // 56 // short modelindex instead of byte
90 "svc_entities", // 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata
91 "svc_unusedlh3", // 58
92 "svc_spawnstaticsound2", // 59 // [coord3] [short] samp [byte] vol [byte] aten
95 //=============================================================================
97 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
99 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
100 int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces
104 CL_ParseStartSoundPacket
107 void CL_ParseStartSoundPacket(int largesoundindex)
117 field_mask = MSG_ReadByte();
119 if (field_mask & SND_VOLUME)
120 volume = MSG_ReadByte ();
122 volume = DEFAULT_SOUND_PACKET_VOLUME;
124 if (field_mask & SND_ATTENUATION)
125 attenuation = MSG_ReadByte () / 64.0;
127 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
129 if (field_mask & SND_LARGEENTITY)
131 ent = (unsigned short) MSG_ReadShort ();
132 channel = MSG_ReadByte ();
136 channel = (unsigned short) MSG_ReadShort ();
141 if (largesoundindex || field_mask & SND_LARGESOUND)
142 sound_num = (unsigned short) MSG_ReadShort ();
144 sound_num = MSG_ReadByte ();
146 if (sound_num >= MAX_SOUNDS)
147 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
150 if (ent >= MAX_EDICTS)
151 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
153 for (i = 0;i < 3;i++)
154 pos[i] = MSG_ReadCoord ();
156 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
163 When the client is taking a long time to load stuff, send keepalive messages
164 so the server doesn't disconnect.
167 void CL_KeepaliveMessage (void)
170 static float lastmsg;
177 return; // no need if server is local
178 if (cls.demoplayback)
181 // read messages from server, should just be nops
183 memcpy (olddata, net_message.data, net_message.cursize);
187 ret = CL_GetMessage ();
191 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
193 break; // nothing waiting
195 Host_Error ("CL_KeepaliveMessage: received a message");
200 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
206 memcpy (net_message.data, olddata, net_message.cursize);
209 time = Sys_DoubleTime ();
210 if (time - lastmsg < 5)
215 Con_Printf ("--> client to server keepalive\n");
217 MSG_WriteByte (&cls.message, clc_nop);
218 NET_SendMessage (cls.netcon, &cls.message);
219 SZ_Clear (&cls.message);
222 void CL_ParseEntityLump(char *entdata)
225 char key[128], value[4096];
226 FOG_clear(); // LordHavoc: no fog until set
227 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
231 if (!COM_ParseToken(&data))
233 if (com_token[0] != '{')
237 if (!COM_ParseToken(&data))
239 if (com_token[0] == '}')
240 break; // end of worldspawn
241 if (com_token[0] == '_')
242 strcpy(key, com_token + 1);
244 strcpy(key, com_token);
245 while (key[strlen(key)-1] == ' ') // remove trailing spaces
246 key[strlen(key)-1] = 0;
247 if (!COM_ParseToken(&data))
249 strcpy(value, com_token);
250 if (!strcmp("sky", key))
252 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
254 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
256 else if (!strcmp("fog", key))
257 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
258 else if (!strcmp("fog_density", key))
259 fog_density = atof(value);
260 else if (!strcmp("fog_red", key))
261 fog_red = atof(value);
262 else if (!strcmp("fog_green", key))
263 fog_green = atof(value);
264 else if (!strcmp("fog_blue", key))
265 fog_blue = atof(value);
270 =====================
273 An svc_signonnum has been received, perform a client side setup
274 =====================
276 static void CL_SignonReply (void)
280 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
285 MSG_WriteByte (&cls.message, clc_stringcmd);
286 MSG_WriteString (&cls.message, "prespawn");
290 MSG_WriteByte (&cls.message, clc_stringcmd);
291 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
293 MSG_WriteByte (&cls.message, clc_stringcmd);
294 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
296 if (cl_pmodel.integer)
298 MSG_WriteByte (&cls.message, clc_stringcmd);
299 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
302 MSG_WriteByte (&cls.message, clc_stringcmd);
303 MSG_WriteString (&cls.message, "spawn");
307 MSG_WriteByte (&cls.message, clc_stringcmd);
308 MSG_WriteString (&cls.message, "begin");
322 qbyte entlife[MAX_EDICTS];
323 // FIXME: this is a lot of memory to be keeping around, this needs to be dynamically allocated and freed
324 static char parse_model_precache[MAX_MODELS][MAX_QPATH];
325 static char parse_sound_precache[MAX_SOUNDS][MAX_QPATH];
326 void CL_ParseServerInfo (void)
330 int nummodels, numsounds;
333 Con_DPrintf ("Serverinfo packet received.\n");
335 // wipe the client_state_t struct
339 // parse protocol version number
341 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
343 Host_Error ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
346 Nehahrademcompatibility = false;
348 Nehahrademcompatibility = true;
349 if (cls.demoplayback && demo_nehahra.integer)
350 Nehahrademcompatibility = true;
352 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
356 cl.maxclients = MSG_ReadByte ();
357 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
359 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
362 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
365 cl.gametype = MSG_ReadByte ();
367 // parse signon message
368 str = MSG_ReadString ();
369 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
371 // seperate the printfs so the server message can have a color
372 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
374 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");
375 Con_Printf ("%c%s\n", 2, str);
378 // check memory integrity
379 Mem_CheckSentinelsGlobal();
381 // disable until we get textures for it
384 memset (cl.model_precache, 0, sizeof(cl.model_precache));
385 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
387 // touch all of the precached models that are still loaded so we can free
388 // anything that isn't needed
390 for (nummodels=1 ; ; nummodels++)
392 CL_KeepaliveMessage ();
393 str = MSG_ReadString ();
396 if (nummodels==MAX_MODELS)
397 Host_Error ("Server sent too many model precaches\n");
398 if (strlen(str) >= MAX_QPATH)
399 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
400 strcpy (parse_model_precache[nummodels], str);
401 Mod_TouchModel (str);
404 // do the same for sounds
405 for (numsounds=1 ; ; numsounds++)
407 CL_KeepaliveMessage ();
408 str = MSG_ReadString ();
411 if (numsounds==MAX_SOUNDS)
412 Host_Error ("Server sent too many sound precaches\n");
413 if (strlen(str) >= MAX_QPATH)
414 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
415 strcpy (parse_sound_precache[numsounds], str);
419 // purge anything that was not touched
422 // now we try to load everything that is new
425 CL_KeepaliveMessage ();
426 cl.model_precache[1] = Mod_ForName (parse_model_precache[1], false, false, true);
427 if (cl.model_precache[1] == NULL)
428 Con_Printf("Map %s not found\n", parse_model_precache[1]);
431 for (i=2 ; i<nummodels ; i++)
433 CL_KeepaliveMessage ();
434 if ((cl.model_precache[i] = Mod_ForName (parse_model_precache[i], false, false, false)) == NULL)
435 Con_Printf("Model %s not found\n", parse_model_precache[i]);
439 S_BeginPrecaching ();
440 for (i=1 ; i<numsounds ; i++)
442 CL_KeepaliveMessage ();
443 cl.sound_precache[i] = S_PrecacheSound (parse_sound_precache[i], true);
448 ent = &cl_entities[0];
449 // entire entity array was cleared, so just fill in a few fields
450 ent->state_current.active = true;
451 ent->render.model = cl.worldmodel = cl.model_precache[1];
452 //ent->render.scale = 1;
453 ent->render.alpha = 1;
454 ent->render.flags = RENDER_SHADOW;
455 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
456 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
457 CL_BoundingBoxForEntity(&ent->render);
458 // clear entlife array
459 memset(entlife, 0, MAX_EDICTS);
466 // noclip is turned off at start
467 noclip_anglehack = false;
469 // check memory integrity
470 Mem_CheckSentinelsGlobal();
473 void CL_ValidateState(entity_state_t *s)
480 if (s->modelindex >= MAX_MODELS)
481 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
483 // colormap is client index + 1
484 if (s->colormap > cl.maxclients)
485 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
487 model = cl.model_precache[s->modelindex];
488 Mod_CheckLoaded(model);
489 if (model && s->frame >= model->numframes)
491 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
494 if (model && s->skin > 0 && s->skin >= model->numskins)
496 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
501 void CL_MoveLerpEntityStates(entity_t *ent)
503 float odelta[3], adelta[3];
504 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
505 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
506 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
508 // we definitely shouldn't lerp
509 ent->persistent.lerpdeltatime = 0;
510 ent->persistent.lerpstarttime = cl.mtime[1];
511 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
512 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
513 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
514 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
516 else if (ent->state_current.flags & RENDER_STEP)
518 // monster interpolation
519 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
521 ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
522 ent->persistent.lerpstarttime = cl.mtime[1];
523 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
524 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
525 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
526 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
532 ent->persistent.lerpstarttime = cl.mtime[1];
533 // no lerp if it's singleplayer
534 if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
535 ent->persistent.lerpdeltatime = 0;
537 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
538 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
539 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
540 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
541 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
549 Parse an entity update message from the server
550 If an entities model or origin changes from frame to frame, it must be
551 relinked. Other attributes can change without relinking.
554 void CL_ParseUpdate (int bits)
560 if (bits & U_MOREBITS)
561 bits |= (MSG_ReadByte()<<8);
562 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
564 bits |= MSG_ReadByte() << 16;
565 if (bits & U_EXTEND2)
566 bits |= MSG_ReadByte() << 24;
569 if (bits & U_LONGENTITY)
570 num = (unsigned) MSG_ReadShort ();
572 num = (unsigned) MSG_ReadByte ();
574 if (num >= MAX_EDICTS)
575 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
577 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
579 ent = cl_entities + num;
581 // note: this inherits the 'active' state of the baseline chosen
582 // (state_baseline is always active, state_current may not be active if
583 // the entity was missing in the last frame)
585 new = ent->state_current;
588 new = ent->state_baseline;
593 new.time = cl.mtime[0];
595 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
596 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
597 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
598 if (bits & U_SKIN) new.skin = MSG_ReadByte();
599 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
600 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
601 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
602 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
603 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
604 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
605 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
606 if (bits & U_STEP) new.flags |= RENDER_STEP;
607 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
608 if (bits & U_SCALE) new.scale = MSG_ReadByte();
609 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
610 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
611 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
612 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
613 if (bits & U_COLORMOD) MSG_ReadByte();
614 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
615 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
616 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
617 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
618 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
620 // LordHavoc: to allow playback of the Nehahra movie
621 if (Nehahrademcompatibility && (bits & U_EXTEND1))
623 // LordHavoc: evil format
624 int i = MSG_ReadFloat();
625 int j = MSG_ReadFloat() * 255.0f;
630 new.effects |= EF_FULLBRIGHT;
634 else if (j == 0 || j >= 255)
641 CL_ValidateState(&new);
643 ent->state_previous = ent->state_current;
644 ent->state_current = new;
645 if (ent->state_current.active)
647 CL_MoveLerpEntityStates(ent);
648 cl_entities_active[ent->state_current.number] = true;
649 // mark as visible (no kill this frame)
650 entlife[ent->state_current.number] = 2;
654 static entity_frame_t entityframe;
655 void CL_ReadEntityFrame(void)
659 EntityFrame_Read(&cl.entitydatabase);
660 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
661 for (i = 0;i < entityframe.numentities;i++)
664 ent = &cl_entities[entityframe.entitydata[i].number];
665 ent->state_previous = ent->state_current;
666 ent->state_current = entityframe.entitydata[i];
667 CL_MoveLerpEntityStates(ent);
668 // the entity lives again...
669 entlife[ent->state_current.number] = 2;
670 cl_entities_active[ent->state_current.number] = true;
672 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
673 VectorCopy(entityframe.eye, cl.viewentoriginnew);
676 void CL_EntityUpdateSetup(void)
680 void CL_EntityUpdateEnd(void)
683 // disable entities that disappeared this frame
684 for (i = 1;i < MAX_EDICTS;i++)
686 // clear only the entities that were active last frame but not this
687 // frame, don't waste time clearing all entities (which would cause
693 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
703 void CL_ParseBaseline (entity_t *ent, int large)
707 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
708 ent->state_baseline.active = true;
711 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
712 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
716 ent->state_baseline.modelindex = MSG_ReadByte ();
717 ent->state_baseline.frame = MSG_ReadByte ();
719 ent->state_baseline.colormap = MSG_ReadByte();
720 ent->state_baseline.skin = MSG_ReadByte();
721 for (i = 0;i < 3;i++)
723 ent->state_baseline.origin[i] = MSG_ReadCoord ();
724 ent->state_baseline.angles[i] = MSG_ReadAngle ();
726 ent->state_baseline.alpha = 255;
727 ent->state_baseline.scale = 16;
728 ent->state_baseline.glowsize = 0;
729 ent->state_baseline.glowcolor = 254;
730 ent->state_previous = ent->state_current = ent->state_baseline;
732 CL_ValidateState(&ent->state_baseline);
740 Server information pertaining to this client only
743 void CL_ParseClientdata (int bits)
748 if (bits & SU_EXTEND1)
749 bits |= (MSG_ReadByte() << 16);
750 if (bits & SU_EXTEND2)
751 bits |= (MSG_ReadByte() << 24);
753 if (bits & SU_VIEWHEIGHT)
754 cl.viewheight = MSG_ReadChar ();
756 cl.viewheight = DEFAULT_VIEWHEIGHT;
758 if (bits & SU_IDEALPITCH)
759 cl.idealpitch = MSG_ReadChar ();
763 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
764 for (i=0 ; i<3 ; i++)
766 if (bits & (SU_PUNCH1<<i) )
769 cl.punchangle[i] = MSG_ReadPreciseAngle();
771 cl.punchangle[i] = MSG_ReadChar();
774 cl.punchangle[i] = 0;
775 if (bits & (SU_PUNCHVEC1<<i))
776 cl.punchvector[i] = MSG_ReadCoord();
778 cl.punchvector[i] = 0;
779 if (bits & (SU_VELOCITY1<<i) )
780 cl.mvelocity[0][i] = MSG_ReadChar()*16;
782 cl.mvelocity[0][i] = 0;
788 for (j=0 ; j<32 ; j++)
789 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
790 cl.item_gettime[j] = cl.time;
794 cl.onground = (bits & SU_ONGROUND) != 0;
795 cl.inwater = (bits & SU_INWATER) != 0;
797 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
798 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
799 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
800 cl.stats[STAT_HEALTH] = MSG_ReadShort();
801 cl.stats[STAT_AMMO] = MSG_ReadByte();
803 cl.stats[STAT_SHELLS] = MSG_ReadByte();
804 cl.stats[STAT_NAILS] = MSG_ReadByte();
805 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
806 cl.stats[STAT_CELLS] = MSG_ReadByte();
810 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
811 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
813 cl.stats[STAT_ACTIVEWEAPON] = i;
815 cl.viewzoomold = cl.viewzoomnew; // for interpolation
816 if (bits & SU_VIEWZOOM)
821 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
829 =====================
831 =====================
833 void CL_ParseStatic (int large)
837 if (cl_num_static_entities >= cl_max_static_entities)
838 Host_Error ("Too many static entities");
839 ent = &cl_static_entities[cl_num_static_entities++];
840 CL_ParseBaseline (ent, large);
842 // copy it to the current state
843 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
844 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
845 ent->render.framelerp = 0;
846 // make torchs play out of sync
847 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
848 ent->render.colormap = -1; // no special coloring
849 ent->render.skinnum = ent->state_baseline.skin;
850 ent->render.effects = ent->state_baseline.effects;
851 ent->render.alpha = 1;
852 //ent->render.scale = 1;
854 //VectorCopy (ent->state_baseline.origin, ent->render.origin);
855 //VectorCopy (ent->state_baseline.angles, ent->render.angles);
857 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);
858 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
859 CL_BoundingBoxForEntity(&ent->render);
861 // This is definitely cheating...
862 if (ent->render.model == NULL)
863 cl_num_static_entities--;
871 void CL_ParseStaticSound (int large)
874 int sound_num, vol, atten;
878 sound_num = (unsigned short) MSG_ReadShort ();
880 sound_num = MSG_ReadByte ();
881 vol = MSG_ReadByte ();
882 atten = MSG_ReadByte ();
884 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
887 void CL_ParseEffect (void)
890 int modelindex, startframe, framecount, framerate;
893 modelindex = MSG_ReadByte ();
894 startframe = MSG_ReadByte ();
895 framecount = MSG_ReadByte ();
896 framerate = MSG_ReadByte ();
898 CL_Effect(org, modelindex, startframe, framecount, framerate);
901 void CL_ParseEffect2 (void)
904 int modelindex, startframe, framecount, framerate;
907 modelindex = MSG_ReadShort ();
908 startframe = MSG_ReadShort ();
909 framecount = MSG_ReadByte ();
910 framerate = MSG_ReadByte ();
912 CL_Effect(org, modelindex, startframe, framecount, framerate);
915 model_t *cl_model_bolt = NULL;
916 model_t *cl_model_bolt2 = NULL;
917 model_t *cl_model_bolt3 = NULL;
918 model_t *cl_model_beam = NULL;
920 sfx_t *cl_sfx_wizhit;
921 sfx_t *cl_sfx_knighthit;
926 sfx_t *cl_sfx_r_exp3;
933 void CL_InitTEnts (void)
935 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
936 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
937 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
938 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
939 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
940 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
941 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
944 void CL_ParseBeam (model_t *m, int lightning)
950 ent = MSG_ReadShort ();
951 MSG_ReadVector(start);
954 if (ent >= MAX_EDICTS)
956 Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
960 // override any beam with the same entity
961 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
963 if (b->entity == ent)
966 b->lightning = lightning;
967 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
969 b->endtime = cl.time + 0.2;
970 VectorCopy (start, b->start);
971 VectorCopy (end, b->end);
977 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
979 if (!b->model || b->endtime < cl.time)
982 b->lightning = lightning;
983 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
985 b->endtime = cl.time + 0.2;
986 VectorCopy (start, b->start);
987 VectorCopy (end, b->end);
991 Con_Printf ("beam list overflow!\n");
994 void CL_ParseTempEntity (void)
1002 int colorStart, colorLength, count;
1003 float velspeed, radius;
1006 type = MSG_ReadByte ();
1010 // spike hitting wall
1011 MSG_ReadVector(pos);
1012 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1013 CL_AllocDlight (NULL, pos, 50, 0.25f, 1.00f, 0.25f, 250, 0.2);
1014 CL_RunParticleEffect (pos, vec3_origin, 20, 30);
1015 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
1018 case TE_KNIGHTSPIKE:
1019 // spike hitting wall
1020 MSG_ReadVector(pos);
1021 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1022 CL_AllocDlight (NULL, pos, 50, 1.0f, 0.60f, 0.20f, 250, 0.2);
1023 CL_RunParticleEffect (pos, vec3_origin, 226, 20);
1024 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
1028 // spike hitting wall
1029 MSG_ReadVector(pos);
1030 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1031 // LordHavoc: changed to spark shower
1032 CL_SparkShower(pos, vec3_origin, 15);
1034 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1039 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1041 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1043 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1047 // quad spike hitting wall
1048 MSG_ReadVector(pos);
1049 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1050 // LordHavoc: changed to spark shower
1051 CL_SparkShower(pos, vec3_origin, 15);
1052 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1053 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1055 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1060 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1062 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1064 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1068 // super spike hitting wall
1069 MSG_ReadVector(pos);
1070 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1071 // LordHavoc: changed to dust shower
1072 CL_SparkShower(pos, vec3_origin, 30);
1074 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1079 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1081 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1083 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1086 case TE_SUPERSPIKEQUAD:
1087 // quad super spike hitting wall
1088 MSG_ReadVector(pos);
1089 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1090 // LordHavoc: changed to dust shower
1091 CL_SparkShower(pos, vec3_origin, 30);
1092 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1094 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1099 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1101 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1103 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1106 // LordHavoc: added for improved blood splatters
1109 MSG_ReadVector(pos);
1110 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1111 dir[0] = MSG_ReadChar ();
1112 dir[1] = MSG_ReadChar ();
1113 dir[2] = MSG_ReadChar ();
1114 count = MSG_ReadByte ();
1115 CL_BloodPuff(pos, dir, count);
1119 MSG_ReadVector(pos);
1120 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1121 CL_BloodPuff(pos, vec3_origin, 10);
1125 MSG_ReadVector(pos);
1126 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1127 dir[0] = MSG_ReadChar ();
1128 dir[1] = MSG_ReadChar ();
1129 dir[2] = MSG_ReadChar ();
1130 count = MSG_ReadByte ();
1131 CL_SparkShower(pos, dir, count);
1134 MSG_ReadVector(pos);
1135 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1136 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1139 // LordHavoc: added for improved gore
1140 case TE_BLOODSHOWER:
1142 MSG_ReadVector(pos); // mins
1143 MSG_ReadVector(pos2); // maxs
1144 velspeed = MSG_ReadCoord (); // speed
1145 count = MSG_ReadShort (); // number of particles
1146 CL_BloodShower(pos, pos2, velspeed, count);
1148 case TE_PARTICLECUBE:
1149 // general purpose particle effect
1150 MSG_ReadVector(pos); // mins
1151 MSG_ReadVector(pos2); // maxs
1152 MSG_ReadVector(dir); // dir
1153 count = MSG_ReadShort (); // number of particles
1154 colorStart = MSG_ReadByte (); // color
1155 colorLength = MSG_ReadByte (); // gravity (1 or 0)
1156 velspeed = MSG_ReadCoord (); // randomvel
1157 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1160 case TE_PARTICLERAIN:
1161 // general purpose particle effect
1162 MSG_ReadVector(pos); // mins
1163 MSG_ReadVector(pos2); // maxs
1164 MSG_ReadVector(dir); // dir
1165 count = MSG_ReadShort (); // number of particles
1166 colorStart = MSG_ReadByte (); // color
1167 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1170 case TE_PARTICLESNOW:
1171 // general purpose particle effect
1172 MSG_ReadVector(pos); // mins
1173 MSG_ReadVector(pos2); // maxs
1174 MSG_ReadVector(dir); // dir
1175 count = MSG_ReadShort (); // number of particles
1176 colorStart = MSG_ReadByte (); // color
1177 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1181 // bullet hitting wall
1182 MSG_ReadVector(pos);
1183 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1184 // LordHavoc: changed to dust shower
1185 CL_SparkShower(pos, vec3_origin, 15);
1188 case TE_GUNSHOTQUAD:
1189 // quad bullet hitting wall
1190 MSG_ReadVector(pos);
1191 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1192 CL_SparkShower(pos, vec3_origin, 15);
1193 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1198 MSG_ReadVector(pos);
1199 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1200 CL_ParticleExplosion (pos);
1201 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1202 CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1203 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1206 case TE_EXPLOSIONQUAD:
1207 // quad rocket explosion
1208 MSG_ReadVector(pos);
1209 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1210 CL_ParticleExplosion (pos);
1211 CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1212 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1216 // Nehahra movie colored lighting explosion
1217 MSG_ReadVector(pos);
1218 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1219 CL_ParticleExplosion (pos);
1220 CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1221 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1224 case TE_EXPLOSIONRGB:
1225 // colored lighting explosion
1226 MSG_ReadVector(pos);
1227 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1228 CL_ParticleExplosion (pos);
1229 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1230 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1231 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1232 CL_AllocDlight (NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1233 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1236 case TE_TAREXPLOSION:
1237 // tarbaby explosion
1238 MSG_ReadVector(pos);
1239 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1240 CL_BlobExplosion (pos);
1242 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1243 CL_AllocDlight (NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
1244 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1248 MSG_ReadVector(pos);
1249 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1250 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1253 case TE_CUSTOMFLASH:
1254 MSG_ReadVector(pos);
1255 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1256 radius = MSG_ReadByte() * 8;
1257 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1258 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1259 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1260 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1261 CL_AllocDlight (NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1265 MSG_ReadVector(pos);
1266 MSG_ReadVector(dir);
1267 count = MSG_ReadByte();
1268 CL_Flames(pos, dir, count);
1274 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1275 CL_ParseBeam (cl_model_bolt, true);
1280 if (!cl_model_bolt2)
1281 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1282 CL_ParseBeam (cl_model_bolt2, true);
1287 if (!cl_model_bolt3)
1288 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1289 CL_ParseBeam (cl_model_bolt3, false);
1294 // grappling hook beam
1296 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1297 CL_ParseBeam (cl_model_beam, false);
1301 // LordHavoc: for compatibility with the Nehahra movie...
1302 case TE_LIGHTNING4NEH:
1303 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false), false);
1307 pos[0] = MSG_ReadCoord ();
1308 pos[1] = MSG_ReadCoord ();
1309 pos[2] = MSG_ReadCoord ();
1310 CL_LavaSplash (pos);
1314 pos[0] = MSG_ReadCoord ();
1315 pos[1] = MSG_ReadCoord ();
1316 pos[2] = MSG_ReadCoord ();
1317 CL_AllocDlight (NULL, pos, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f);
1318 // CL_TeleportSplash (pos);
1322 // color mapped explosion
1323 MSG_ReadVector(pos);
1324 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1325 colorStart = MSG_ReadByte ();
1326 colorLength = MSG_ReadByte ();
1327 CL_ParticleExplosion2 (pos, colorStart, colorLength);
1328 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1329 CL_AllocDlight (NULL, pos, 350, tempcolor[0] * (1.0f / 255.0f), tempcolor[1] * (1.0f / 255.0f), tempcolor[2] * (1.0f / 255.0f), 700, 0.5);
1330 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1334 MSG_ReadVector(pos);
1335 MSG_ReadVector(pos2);
1336 MSG_ReadVector(dir);
1337 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1338 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1342 MSG_ReadVector(pos);
1343 MSG_ReadVector(dir);
1344 count = MSG_ReadByte ();
1345 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1346 CL_Tei_Smoke(pos, dir, count);
1349 case TE_TEI_BIGEXPLOSION:
1350 MSG_ReadVector(pos);
1351 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1352 CL_ParticleExplosion (pos);
1353 CL_AllocDlight (NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
1354 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1357 case TE_TEI_PLASMAHIT:
1358 MSG_ReadVector(pos);
1359 MSG_ReadVector(dir);
1360 count = MSG_ReadByte ();
1361 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 5);
1362 CL_Tei_PlasmaHit(pos, dir, count);
1363 CL_AllocDlight (NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
1367 Host_Error ("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1371 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1373 static qbyte cgamenetbuffer[65536];
1376 =====================
1377 CL_ParseServerMessage
1378 =====================
1380 int parsingerror = false;
1381 void CL_ParseServerMessage (void)
1384 int i, entitiesupdated;
1386 char *cmdlogname[32], *temp;
1387 int cmdindex, cmdcount = 0;
1390 // if recording demos, copy the message out
1392 if (cl_shownet.integer == 1)
1393 Con_Printf ("%i ",net_message.cursize);
1394 else if (cl_shownet.integer == 2)
1395 Con_Printf ("------------------\n");
1397 cl.onground = false; // unless the server says otherwise
1399 // parse the message
1401 MSG_BeginReading ();
1403 entitiesupdated = false;
1405 parsingerror = true;
1410 Host_Error ("CL_ParseServerMessage: Bad server message");
1412 cmd = MSG_ReadByte ();
1416 SHOWNET("END OF MESSAGE");
1417 break; // end of message
1420 cmdindex = cmdcount & 31;
1422 cmdlog[cmdindex] = cmd;
1424 // if the high bit of the command byte is set, it is a fast update
1427 // 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)
1429 cmdlogname[cmdindex] = temp;
1430 SHOWNET("fast update");
1431 if (cls.signon == SIGNONS - 1)
1433 // first update is the final signon stage
1434 cls.signon = SIGNONS;
1437 CL_ParseUpdate (cmd&127);
1441 SHOWNET(svc_strings[cmd]);
1442 cmdlogname[cmdindex] = svc_strings[cmd];
1443 if (!cmdlogname[cmdindex])
1445 // 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)
1447 cmdlogname[cmdindex] = temp;
1455 char description[32*64], temp[64];
1457 strcpy(description, "packet dump: ");
1461 count = cmdcount - i;
1465 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1466 strcat(description, temp);
1471 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1472 Con_Printf("%s", description);
1473 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1481 if (!entitiesupdated)
1483 // this is a new frame, we'll be seeing entities,
1484 // so prepare for entity updates
1485 CL_EntityUpdateSetup();
1486 entitiesupdated = true;
1488 cl.mtime[1] = cl.mtime[0];
1489 cl.mtime[0] = MSG_ReadFloat ();
1492 case svc_clientdata:
1493 i = MSG_ReadShort ();
1494 CL_ParseClientdata (i);
1498 i = MSG_ReadLong ();
1499 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1500 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1501 Nehahrademcompatibility = false;
1503 Nehahrademcompatibility = true;
1504 if (cls.demoplayback && demo_nehahra.integer)
1505 Nehahrademcompatibility = true;
1507 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1511 case svc_disconnect:
1512 Host_EndGame ("Server disconnected\n");
1515 Con_Printf ("%s", MSG_ReadString ());
1518 case svc_centerprint:
1519 SCR_CenterPrint (MSG_ReadString ());
1523 Cbuf_AddText (MSG_ReadString ());
1530 case svc_serverinfo:
1531 CL_ParseServerInfo ();
1535 for (i=0 ; i<3 ; i++)
1536 cl.viewangles[i] = MSG_ReadAngle ();
1540 cl.viewentity = MSG_ReadShort ();
1541 // LordHavoc: assume first setview recieved is the real player entity
1542 if (!cl.playerentity)
1543 cl.playerentity = cl.viewentity;
1546 case svc_lightstyle:
1547 i = MSG_ReadByte ();
1548 if (i >= MAX_LIGHTSTYLES)
1549 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1550 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1551 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1552 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1556 CL_ParseStartSoundPacket(false);
1560 CL_ParseStartSoundPacket(true);
1564 i = MSG_ReadShort();
1565 S_StopSound(i>>3, i&7);
1568 case svc_updatename:
1569 i = MSG_ReadByte ();
1570 if (i >= cl.maxclients)
1571 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1572 strcpy (cl.scores[i].name, MSG_ReadString ());
1575 case svc_updatefrags:
1576 i = MSG_ReadByte ();
1577 if (i >= cl.maxclients)
1578 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1579 cl.scores[i].frags = MSG_ReadShort ();
1582 case svc_updatecolors:
1583 i = MSG_ReadByte ();
1584 if (i >= cl.maxclients)
1585 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1586 cl.scores[i].colors = MSG_ReadByte ();
1590 CL_ParseParticleEffect ();
1601 case svc_spawnbaseline:
1602 i = MSG_ReadShort ();
1603 if (i < 0 || i >= MAX_EDICTS)
1604 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1605 CL_ParseBaseline (cl_entities + i, false);
1607 case svc_spawnbaseline2:
1608 i = MSG_ReadShort ();
1609 if (i < 0 || i >= MAX_EDICTS)
1610 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1611 CL_ParseBaseline (cl_entities + i, true);
1613 case svc_spawnstatic:
1614 CL_ParseStatic (false);
1616 case svc_spawnstatic2:
1617 CL_ParseStatic (true);
1619 case svc_temp_entity:
1620 CL_ParseTempEntity ();
1624 cl.paused = MSG_ReadByte ();
1632 i = MSG_ReadByte ();
1633 if (i <= cls.signon)
1634 Host_Error ("Received signon %i when at %i", i, cls.signon);
1639 case svc_killedmonster:
1640 cl.stats[STAT_MONSTERS]++;
1643 case svc_foundsecret:
1644 cl.stats[STAT_SECRETS]++;
1647 case svc_updatestat:
1648 i = MSG_ReadByte ();
1649 if (i < 0 || i >= MAX_CL_STATS)
1650 Host_Error ("svc_updatestat: %i is invalid", i);
1651 cl.stats[i] = MSG_ReadLong ();
1654 case svc_spawnstaticsound:
1655 CL_ParseStaticSound (false);
1658 case svc_spawnstaticsound2:
1659 CL_ParseStaticSound (true);
1663 cl.cdtrack = MSG_ReadByte ();
1664 cl.looptrack = MSG_ReadByte ();
1665 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1666 CDAudio_Play ((qbyte)cls.forcetrack, true);
1668 CDAudio_Play ((qbyte)cl.cdtrack, true);
1671 case svc_intermission:
1672 cl.intermission = 1;
1673 cl.completed_time = cl.time;
1677 cl.intermission = 2;
1678 cl.completed_time = cl.time;
1679 SCR_CenterPrint (MSG_ReadString ());
1683 cl.intermission = 3;
1684 cl.completed_time = cl.time;
1685 SCR_CenterPrint (MSG_ReadString ());
1688 case svc_sellscreen:
1689 Cmd_ExecuteString ("help", src_command);
1692 SHOWLMP_decodehide();
1695 SHOWLMP_decodeshow();
1698 R_SetSkyBox(MSG_ReadString());
1703 length = (int) ((unsigned short) MSG_ReadShort());
1704 for (i = 0;i < length;i++)
1705 cgamenetbuffer[i] = MSG_ReadByte();
1707 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1711 if (cls.signon == SIGNONS - 1)
1713 // first update is the final signon stage
1714 cls.signon = SIGNONS;
1717 CL_ReadEntityFrame();
1722 if (entitiesupdated)
1723 CL_EntityUpdateEnd();
1725 parsingerror = false;
1728 void CL_Parse_DumpPacket(void)
1732 Con_Printf("Packet dump:\n");
1733 SZ_HexDumpToConsole(&net_message);
1734 parsingerror = false;
1737 void CL_Parse_Init(void)
1739 // LordHavoc: added demo_nehahra cvar
1740 Cvar_RegisterVariable (&demo_nehahra);
1741 if (gamemode == GAME_NEHAHRA)
1742 Cvar_SetValue("demo_nehahra", 1);