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 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
455 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
456 CL_BoundingBoxForEntity(&ent->render);
457 // clear entlife array
458 memset(entlife, 0, MAX_EDICTS);
465 // noclip is turned off at start
466 noclip_anglehack = false;
468 // check memory integrity
469 Mem_CheckSentinelsGlobal();
472 void CL_ValidateState(entity_state_t *s)
479 if (s->modelindex >= MAX_MODELS)
480 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
482 // colormap is client index + 1
483 if (s->colormap > cl.maxclients)
484 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
486 model = cl.model_precache[s->modelindex];
487 Mod_CheckLoaded(model);
488 if (model && s->frame >= model->numframes)
490 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
493 if (model && s->skin > 0 && s->skin >= model->numskins)
495 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
500 void CL_MoveLerpEntityStates(entity_t *ent)
502 float odelta[3], adelta[3];
503 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
504 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
505 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
507 // we definitely shouldn't lerp
508 ent->persistent.lerpdeltatime = 0;
509 ent->persistent.lerpstarttime = cl.mtime[1];
510 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
511 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
512 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
513 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
515 else if (ent->state_current.flags & RENDER_STEP)
517 // monster interpolation
518 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
520 ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
521 ent->persistent.lerpstarttime = cl.mtime[1];
522 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
523 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
524 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
525 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
531 ent->persistent.lerpstarttime = cl.mtime[1];
532 // no lerp if it's singleplayer
533 if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
534 ent->persistent.lerpdeltatime = 0;
536 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
537 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
538 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
539 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
540 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
548 Parse an entity update message from the server
549 If an entities model or origin changes from frame to frame, it must be
550 relinked. Other attributes can change without relinking.
553 void CL_ParseUpdate (int bits)
559 if (bits & U_MOREBITS)
560 bits |= (MSG_ReadByte()<<8);
561 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
563 bits |= MSG_ReadByte() << 16;
564 if (bits & U_EXTEND2)
565 bits |= MSG_ReadByte() << 24;
568 if (bits & U_LONGENTITY)
569 num = (unsigned) MSG_ReadShort ();
571 num = (unsigned) MSG_ReadByte ();
573 if (num >= MAX_EDICTS)
574 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
576 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
578 ent = cl_entities + num;
580 // note: this inherits the 'active' state of the baseline chosen
581 // (state_baseline is always active, state_current may not be active if
582 // the entity was missing in the last frame)
584 new = ent->state_current;
587 new = ent->state_baseline;
592 new.time = cl.mtime[0];
594 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
595 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
596 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
597 if (bits & U_SKIN) new.skin = MSG_ReadByte();
598 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
599 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
600 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
601 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
602 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
603 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
604 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
605 if (bits & U_STEP) new.flags |= RENDER_STEP;
606 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
607 if (bits & U_SCALE) new.scale = MSG_ReadByte();
608 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
609 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
610 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
611 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
612 if (bits & U_COLORMOD) MSG_ReadByte();
613 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
614 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
615 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
616 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
617 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
619 // LordHavoc: to allow playback of the Nehahra movie
620 if (Nehahrademcompatibility && (bits & U_EXTEND1))
622 // LordHavoc: evil format
623 int i = MSG_ReadFloat();
624 int j = MSG_ReadFloat() * 255.0f;
629 new.effects |= EF_FULLBRIGHT;
633 else if (j == 0 || j >= 255)
640 CL_ValidateState(&new);
642 ent->state_previous = ent->state_current;
643 ent->state_current = new;
644 if (ent->state_current.active)
646 CL_MoveLerpEntityStates(ent);
647 cl_entities_active[ent->state_current.number] = true;
648 // mark as visible (no kill this frame)
649 entlife[ent->state_current.number] = 2;
653 static entity_frame_t entityframe;
654 void CL_ReadEntityFrame(void)
658 EntityFrame_Read(&cl.entitydatabase);
659 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
660 for (i = 0;i < entityframe.numentities;i++)
663 ent = &cl_entities[entityframe.entitydata[i].number];
664 ent->state_previous = ent->state_current;
665 ent->state_current = entityframe.entitydata[i];
666 CL_MoveLerpEntityStates(ent);
667 // the entity lives again...
668 entlife[ent->state_current.number] = 2;
669 cl_entities_active[ent->state_current.number] = true;
671 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
672 VectorCopy(entityframe.eye, cl.viewentoriginnew);
675 void CL_EntityUpdateSetup(void)
679 void CL_EntityUpdateEnd(void)
682 // disable entities that disappeared this frame
683 for (i = 1;i < MAX_EDICTS;i++)
685 // clear only the entities that were active last frame but not this
686 // frame, don't waste time clearing all entities (which would cause
692 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
702 void CL_ParseBaseline (entity_t *ent, int large)
706 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
707 ent->state_baseline.active = true;
710 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
711 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
715 ent->state_baseline.modelindex = MSG_ReadByte ();
716 ent->state_baseline.frame = MSG_ReadByte ();
718 ent->state_baseline.colormap = MSG_ReadByte();
719 ent->state_baseline.skin = MSG_ReadByte();
720 for (i = 0;i < 3;i++)
722 ent->state_baseline.origin[i] = MSG_ReadCoord ();
723 ent->state_baseline.angles[i] = MSG_ReadAngle ();
725 ent->state_baseline.alpha = 255;
726 ent->state_baseline.scale = 16;
727 ent->state_baseline.glowsize = 0;
728 ent->state_baseline.glowcolor = 254;
729 ent->state_previous = ent->state_current = ent->state_baseline;
731 CL_ValidateState(&ent->state_baseline);
739 Server information pertaining to this client only
742 void CL_ParseClientdata (int bits)
747 if (bits & SU_EXTEND1)
748 bits |= (MSG_ReadByte() << 16);
749 if (bits & SU_EXTEND2)
750 bits |= (MSG_ReadByte() << 24);
752 if (bits & SU_VIEWHEIGHT)
753 cl.viewheight = MSG_ReadChar ();
755 cl.viewheight = DEFAULT_VIEWHEIGHT;
757 if (bits & SU_IDEALPITCH)
758 cl.idealpitch = MSG_ReadChar ();
762 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
763 for (i=0 ; i<3 ; i++)
765 if (bits & (SU_PUNCH1<<i) )
768 cl.punchangle[i] = MSG_ReadPreciseAngle();
770 cl.punchangle[i] = MSG_ReadChar();
773 cl.punchangle[i] = 0;
774 if (bits & (SU_PUNCHVEC1<<i))
775 cl.punchvector[i] = MSG_ReadCoord();
777 cl.punchvector[i] = 0;
778 if (bits & (SU_VELOCITY1<<i) )
779 cl.mvelocity[0][i] = MSG_ReadChar()*16;
781 cl.mvelocity[0][i] = 0;
787 for (j=0 ; j<32 ; j++)
788 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
789 cl.item_gettime[j] = cl.time;
793 cl.onground = (bits & SU_ONGROUND) != 0;
794 cl.inwater = (bits & SU_INWATER) != 0;
796 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
797 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
798 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
799 cl.stats[STAT_HEALTH] = MSG_ReadShort();
800 cl.stats[STAT_AMMO] = MSG_ReadByte();
802 cl.stats[STAT_SHELLS] = MSG_ReadByte();
803 cl.stats[STAT_NAILS] = MSG_ReadByte();
804 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
805 cl.stats[STAT_CELLS] = MSG_ReadByte();
809 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
810 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
812 cl.stats[STAT_ACTIVEWEAPON] = i;
814 cl.viewzoomold = cl.viewzoomnew; // for interpolation
815 if (bits & SU_VIEWZOOM)
820 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
828 =====================
830 =====================
832 void CL_ParseStatic (int large)
836 if (cl_num_static_entities >= cl_max_static_entities)
837 Host_Error ("Too many static entities");
838 ent = &cl_static_entities[cl_num_static_entities++];
839 CL_ParseBaseline (ent, large);
841 // copy it to the current state
842 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
843 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
844 ent->render.framelerp = 0;
845 // make torchs play out of sync
846 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
847 ent->render.colormap = -1; // no special coloring
848 ent->render.skinnum = ent->state_baseline.skin;
849 ent->render.effects = ent->state_baseline.effects;
850 ent->render.alpha = 1;
851 //ent->render.scale = 1;
853 //VectorCopy (ent->state_baseline.origin, ent->render.origin);
854 //VectorCopy (ent->state_baseline.angles, ent->render.angles);
856 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);
857 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
858 CL_BoundingBoxForEntity(&ent->render);
860 // This is definitely cheating...
861 if (ent->render.model == NULL)
862 cl_num_static_entities--;
870 void CL_ParseStaticSound (int large)
873 int sound_num, vol, atten;
877 sound_num = (unsigned short) MSG_ReadShort ();
879 sound_num = MSG_ReadByte ();
880 vol = MSG_ReadByte ();
881 atten = MSG_ReadByte ();
883 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
886 void CL_ParseEffect (void)
889 int modelindex, startframe, framecount, framerate;
892 modelindex = MSG_ReadByte ();
893 startframe = MSG_ReadByte ();
894 framecount = MSG_ReadByte ();
895 framerate = MSG_ReadByte ();
897 CL_Effect(org, modelindex, startframe, framecount, framerate);
900 void CL_ParseEffect2 (void)
903 int modelindex, startframe, framecount, framerate;
906 modelindex = MSG_ReadShort ();
907 startframe = MSG_ReadShort ();
908 framecount = MSG_ReadByte ();
909 framerate = MSG_ReadByte ();
911 CL_Effect(org, modelindex, startframe, framecount, framerate);
914 model_t *cl_model_bolt = NULL;
915 model_t *cl_model_bolt2 = NULL;
916 model_t *cl_model_bolt3 = NULL;
917 model_t *cl_model_beam = NULL;
919 sfx_t *cl_sfx_wizhit;
920 sfx_t *cl_sfx_knighthit;
925 sfx_t *cl_sfx_r_exp3;
932 void CL_InitTEnts (void)
934 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
935 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
936 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
937 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
938 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
939 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
940 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
943 void CL_ParseBeam (model_t *m, int lightning)
949 ent = MSG_ReadShort ();
950 MSG_ReadVector(start);
953 if (ent >= MAX_EDICTS)
955 Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
959 // override any beam with the same entity
960 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
962 if (b->entity == ent)
965 b->lightning = lightning;
966 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
968 b->endtime = cl.time + 0.2;
969 VectorCopy (start, b->start);
970 VectorCopy (end, b->end);
976 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
978 if (!b->model || b->endtime < cl.time)
981 b->lightning = lightning;
982 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
984 b->endtime = cl.time + 0.2;
985 VectorCopy (start, b->start);
986 VectorCopy (end, b->end);
990 Con_Printf ("beam list overflow!\n");
993 void CL_ParseTempEntity (void)
1001 int colorStart, colorLength, count;
1002 float velspeed, radius;
1005 type = MSG_ReadByte ();
1009 // spike hitting wall
1010 MSG_ReadVector(pos);
1011 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1012 CL_RunParticleEffect (pos, vec3_origin, 20, 30);
1013 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
1016 case TE_KNIGHTSPIKE:
1017 // spike hitting wall
1018 MSG_ReadVector(pos);
1019 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1020 CL_RunParticleEffect (pos, vec3_origin, 226, 20);
1021 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
1025 // spike hitting wall
1026 MSG_ReadVector(pos);
1027 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1028 // LordHavoc: changed to spark shower
1029 CL_SparkShower(pos, vec3_origin, 15);
1031 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1036 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1038 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1040 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1044 // quad spike hitting wall
1045 MSG_ReadVector(pos);
1046 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1047 // LordHavoc: changed to spark shower
1048 CL_SparkShower(pos, vec3_origin, 15);
1049 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1050 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1052 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1057 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1059 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1061 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1065 // super spike hitting wall
1066 MSG_ReadVector(pos);
1067 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1068 // LordHavoc: changed to dust shower
1069 CL_SparkShower(pos, vec3_origin, 30);
1071 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1076 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1078 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1080 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1083 case TE_SUPERSPIKEQUAD:
1084 // quad super spike hitting wall
1085 MSG_ReadVector(pos);
1086 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1087 // LordHavoc: changed to dust shower
1088 CL_SparkShower(pos, vec3_origin, 30);
1089 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1091 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1096 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1098 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1100 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1103 // LordHavoc: added for improved blood splatters
1106 MSG_ReadVector(pos);
1107 dir[0] = MSG_ReadChar ();
1108 dir[1] = MSG_ReadChar ();
1109 dir[2] = MSG_ReadChar ();
1110 count = MSG_ReadByte ();
1111 CL_BloodPuff(pos, dir, count);
1115 MSG_ReadVector(pos);
1116 CL_BloodPuff(pos, vec3_origin, 10);
1120 MSG_ReadVector(pos);
1121 dir[0] = MSG_ReadChar ();
1122 dir[1] = MSG_ReadChar ();
1123 dir[2] = MSG_ReadChar ();
1124 count = MSG_ReadByte ();
1125 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1126 CL_SparkShower(pos, dir, count);
1129 MSG_ReadVector(pos);
1130 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1131 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1134 // LordHavoc: added for improved gore
1135 case TE_BLOODSHOWER:
1137 MSG_ReadVector(pos); // mins
1138 MSG_ReadVector(pos2); // maxs
1139 velspeed = MSG_ReadCoord (); // speed
1140 count = MSG_ReadShort (); // number of particles
1141 CL_BloodShower(pos, pos2, velspeed, count);
1143 case TE_PARTICLECUBE:
1144 // general purpose particle effect
1145 MSG_ReadVector(pos); // mins
1146 MSG_ReadVector(pos2); // maxs
1147 MSG_ReadVector(dir); // dir
1148 count = MSG_ReadShort (); // number of particles
1149 colorStart = MSG_ReadByte (); // color
1150 colorLength = MSG_ReadByte (); // gravity (1 or 0)
1151 velspeed = MSG_ReadCoord (); // randomvel
1152 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1155 case TE_PARTICLERAIN:
1156 // general purpose particle effect
1157 MSG_ReadVector(pos); // mins
1158 MSG_ReadVector(pos2); // maxs
1159 MSG_ReadVector(dir); // dir
1160 count = MSG_ReadShort (); // number of particles
1161 colorStart = MSG_ReadByte (); // color
1162 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1165 case TE_PARTICLESNOW:
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, 1);
1176 // bullet hitting wall
1177 MSG_ReadVector(pos);
1178 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1179 // LordHavoc: changed to dust shower
1180 CL_SparkShower(pos, vec3_origin, 15);
1183 case TE_GUNSHOTQUAD:
1184 // quad bullet hitting wall
1185 MSG_ReadVector(pos);
1186 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1187 CL_SparkShower(pos, vec3_origin, 15);
1188 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1193 MSG_ReadVector(pos);
1194 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1195 CL_ParticleExplosion (pos);
1196 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1197 CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1198 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1201 case TE_EXPLOSIONQUAD:
1202 // quad rocket explosion
1203 MSG_ReadVector(pos);
1204 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1205 CL_ParticleExplosion (pos);
1206 CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1207 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1211 // Nehahra movie colored lighting explosion
1212 MSG_ReadVector(pos);
1213 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1214 CL_ParticleExplosion (pos);
1215 CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1216 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1219 case TE_EXPLOSIONRGB:
1220 // colored lighting explosion
1221 MSG_ReadVector(pos);
1222 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1223 CL_ParticleExplosion (pos);
1224 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1225 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1226 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1227 CL_AllocDlight (NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1228 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1231 case TE_TAREXPLOSION:
1232 // tarbaby explosion
1233 MSG_ReadVector(pos);
1234 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1235 CL_BlobExplosion (pos);
1237 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1238 CL_AllocDlight (NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
1239 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1243 MSG_ReadVector(pos);
1244 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1245 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1248 case TE_CUSTOMFLASH:
1249 MSG_ReadVector(pos);
1250 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1251 radius = MSG_ReadByte() * 8;
1252 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1253 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1254 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1255 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1256 CL_AllocDlight (NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1260 MSG_ReadVector(pos);
1261 MSG_ReadVector(dir);
1262 count = MSG_ReadByte();
1263 CL_Flames(pos, dir, count);
1269 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1270 CL_ParseBeam (cl_model_bolt, true);
1275 if (!cl_model_bolt2)
1276 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1277 CL_ParseBeam (cl_model_bolt2, true);
1282 if (!cl_model_bolt3)
1283 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1284 CL_ParseBeam (cl_model_bolt3, false);
1289 // grappling hook beam
1291 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1292 CL_ParseBeam (cl_model_beam, false);
1296 // LordHavoc: for compatibility with the Nehahra movie...
1297 case TE_LIGHTNING4NEH:
1298 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false), false);
1302 pos[0] = MSG_ReadCoord ();
1303 pos[1] = MSG_ReadCoord ();
1304 pos[2] = MSG_ReadCoord ();
1305 CL_LavaSplash (pos);
1309 pos[0] = MSG_ReadCoord ();
1310 pos[1] = MSG_ReadCoord ();
1311 pos[2] = MSG_ReadCoord ();
1312 CL_AllocDlight (NULL, pos, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f);
1313 // CL_TeleportSplash (pos);
1317 // color mapped explosion
1318 MSG_ReadVector(pos);
1319 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1320 colorStart = MSG_ReadByte ();
1321 colorLength = MSG_ReadByte ();
1322 CL_ParticleExplosion2 (pos, colorStart, colorLength);
1323 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1324 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);
1325 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1329 MSG_ReadVector(pos);
1330 MSG_ReadVector(pos2);
1331 MSG_ReadVector(dir);
1332 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1333 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1337 MSG_ReadVector(pos);
1338 MSG_ReadVector(dir);
1339 count = MSG_ReadByte ();
1340 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1341 CL_Tei_Smoke(pos, dir, count);
1344 case TE_TEI_BIGEXPLOSION:
1345 MSG_ReadVector(pos);
1346 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1347 CL_ParticleExplosion (pos);
1348 CL_AllocDlight (NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
1349 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1352 case TE_TEI_PLASMAHIT:
1353 MSG_ReadVector(pos);
1354 MSG_ReadVector(dir);
1355 count = MSG_ReadByte ();
1356 Mod_FindNonSolidLocation(pos, cl.worldmodel);
1357 CL_Tei_PlasmaHit(pos, dir, count);
1358 CL_AllocDlight (NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
1362 Host_Error ("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1366 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1368 static qbyte cgamenetbuffer[65536];
1371 =====================
1372 CL_ParseServerMessage
1373 =====================
1375 int parsingerror = false;
1376 void CL_ParseServerMessage (void)
1379 int i, entitiesupdated;
1381 char *cmdlogname[32], *temp;
1382 int cmdindex, cmdcount = 0;
1385 // if recording demos, copy the message out
1387 if (cl_shownet.integer == 1)
1388 Con_Printf ("%i ",net_message.cursize);
1389 else if (cl_shownet.integer == 2)
1390 Con_Printf ("------------------\n");
1392 cl.onground = false; // unless the server says otherwise
1394 // parse the message
1396 MSG_BeginReading ();
1398 entitiesupdated = false;
1400 parsingerror = true;
1405 Host_Error ("CL_ParseServerMessage: Bad server message");
1407 cmd = MSG_ReadByte ();
1411 SHOWNET("END OF MESSAGE");
1412 break; // end of message
1415 cmdindex = cmdcount & 31;
1417 cmdlog[cmdindex] = cmd;
1419 // if the high bit of the command byte is set, it is a fast update
1422 // 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)
1424 cmdlogname[cmdindex] = temp;
1425 SHOWNET("fast update");
1426 if (cls.signon == SIGNONS - 1)
1428 // first update is the final signon stage
1429 cls.signon = SIGNONS;
1432 CL_ParseUpdate (cmd&127);
1436 SHOWNET(svc_strings[cmd]);
1437 cmdlogname[cmdindex] = svc_strings[cmd];
1438 if (!cmdlogname[cmdindex])
1440 // 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)
1442 cmdlogname[cmdindex] = temp;
1450 char description[32*64], temp[64];
1452 strcpy(description, "packet dump: ");
1456 count = cmdcount - i;
1460 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1461 strcat(description, temp);
1466 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1467 Con_Printf("%s", description);
1468 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1476 if (!entitiesupdated)
1478 // this is a new frame, we'll be seeing entities,
1479 // so prepare for entity updates
1480 CL_EntityUpdateSetup();
1481 entitiesupdated = true;
1483 cl.mtime[1] = cl.mtime[0];
1484 cl.mtime[0] = MSG_ReadFloat ();
1487 case svc_clientdata:
1488 i = MSG_ReadShort ();
1489 CL_ParseClientdata (i);
1493 i = MSG_ReadLong ();
1494 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1495 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1496 Nehahrademcompatibility = false;
1498 Nehahrademcompatibility = true;
1499 if (cls.demoplayback && demo_nehahra.integer)
1500 Nehahrademcompatibility = true;
1502 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1506 case svc_disconnect:
1507 Host_EndGame ("Server disconnected\n");
1510 Con_Printf ("%s", MSG_ReadString ());
1513 case svc_centerprint:
1514 SCR_CenterPrint (MSG_ReadString ());
1518 Cbuf_AddText (MSG_ReadString ());
1525 case svc_serverinfo:
1526 CL_ParseServerInfo ();
1530 for (i=0 ; i<3 ; i++)
1531 cl.viewangles[i] = MSG_ReadAngle ();
1535 cl.viewentity = MSG_ReadShort ();
1536 // LordHavoc: assume first setview recieved is the real player entity
1537 if (!cl.playerentity)
1538 cl.playerentity = cl.viewentity;
1541 case svc_lightstyle:
1542 i = MSG_ReadByte ();
1543 if (i >= MAX_LIGHTSTYLES)
1544 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1545 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1546 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1547 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1551 CL_ParseStartSoundPacket(false);
1555 CL_ParseStartSoundPacket(true);
1559 i = MSG_ReadShort();
1560 S_StopSound(i>>3, i&7);
1563 case svc_updatename:
1564 i = MSG_ReadByte ();
1565 if (i >= cl.maxclients)
1566 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1567 strcpy (cl.scores[i].name, MSG_ReadString ());
1570 case svc_updatefrags:
1571 i = MSG_ReadByte ();
1572 if (i >= cl.maxclients)
1573 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1574 cl.scores[i].frags = MSG_ReadShort ();
1577 case svc_updatecolors:
1578 i = MSG_ReadByte ();
1579 if (i >= cl.maxclients)
1580 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1581 cl.scores[i].colors = MSG_ReadByte ();
1585 CL_ParseParticleEffect ();
1596 case svc_spawnbaseline:
1597 i = MSG_ReadShort ();
1598 if (i < 0 || i >= MAX_EDICTS)
1599 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1600 CL_ParseBaseline (cl_entities + i, false);
1602 case svc_spawnbaseline2:
1603 i = MSG_ReadShort ();
1604 if (i < 0 || i >= MAX_EDICTS)
1605 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1606 CL_ParseBaseline (cl_entities + i, true);
1608 case svc_spawnstatic:
1609 CL_ParseStatic (false);
1611 case svc_spawnstatic2:
1612 CL_ParseStatic (true);
1614 case svc_temp_entity:
1615 CL_ParseTempEntity ();
1619 cl.paused = MSG_ReadByte ();
1627 i = MSG_ReadByte ();
1628 if (i <= cls.signon)
1629 Host_Error ("Received signon %i when at %i", i, cls.signon);
1634 case svc_killedmonster:
1635 cl.stats[STAT_MONSTERS]++;
1638 case svc_foundsecret:
1639 cl.stats[STAT_SECRETS]++;
1642 case svc_updatestat:
1643 i = MSG_ReadByte ();
1644 if (i < 0 || i >= MAX_CL_STATS)
1645 Host_Error ("svc_updatestat: %i is invalid", i);
1646 cl.stats[i] = MSG_ReadLong ();
1649 case svc_spawnstaticsound:
1650 CL_ParseStaticSound (false);
1653 case svc_spawnstaticsound2:
1654 CL_ParseStaticSound (true);
1658 cl.cdtrack = MSG_ReadByte ();
1659 cl.looptrack = MSG_ReadByte ();
1660 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1661 CDAudio_Play ((qbyte)cls.forcetrack, true);
1663 CDAudio_Play ((qbyte)cl.cdtrack, true);
1666 case svc_intermission:
1667 cl.intermission = 1;
1668 cl.completed_time = cl.time;
1672 cl.intermission = 2;
1673 cl.completed_time = cl.time;
1674 SCR_CenterPrint (MSG_ReadString ());
1678 cl.intermission = 3;
1679 cl.completed_time = cl.time;
1680 SCR_CenterPrint (MSG_ReadString ());
1683 case svc_sellscreen:
1684 Cmd_ExecuteString ("help", src_command);
1687 SHOWLMP_decodehide();
1690 SHOWLMP_decodeshow();
1693 R_SetSkyBox(MSG_ReadString());
1698 length = (int) ((unsigned short) MSG_ReadShort());
1699 for (i = 0;i < length;i++)
1700 cgamenetbuffer[i] = MSG_ReadByte();
1702 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1706 if (cls.signon == SIGNONS - 1)
1708 // first update is the final signon stage
1709 cls.signon = SIGNONS;
1712 CL_ReadEntityFrame();
1717 if (entitiesupdated)
1718 CL_EntityUpdateEnd();
1720 parsingerror = false;
1723 void CL_Parse_DumpPacket(void)
1727 Con_Printf("Packet dump:\n");
1728 SZ_HexDumpToConsole(&net_message);
1729 parsingerror = false;
1732 void CL_Parse_Init(void)
1734 // LordHavoc: added demo_nehahra cvar
1735 Cvar_RegisterVariable (&demo_nehahra);
1736 if (gamemode == GAME_NEHAHRA)
1737 Cvar_SetValue("demo_nehahra", 1);