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
23 #include "cl_collision.h"
25 char *svc_strings[128] =
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
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
54 "OBSOLETE svc_spawnbinary",
57 "svc_temp_entity", // <variable>
63 "svc_spawnstaticsound",
65 "svc_finale", // [string] music [string] text
66 "svc_cdtrack", // [byte] track [byte] looptrack
69 "svc_showlmp", // [string] iconlabel [string] lmpfile [short] x [short] y
70 "svc_hidelmp", // [string] iconlabel
71 "svc_skybox", // [string] skyname
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
96 //=============================================================================
98 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
100 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
101 int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces
103 mempool_t *cl_scores_mempool;
107 CL_ParseStartSoundPacket
110 void CL_ParseStartSoundPacket(int largesoundindex)
120 field_mask = MSG_ReadByte();
122 if (field_mask & SND_VOLUME)
123 volume = MSG_ReadByte ();
125 volume = DEFAULT_SOUND_PACKET_VOLUME;
127 if (field_mask & SND_ATTENUATION)
128 attenuation = MSG_ReadByte () / 64.0;
130 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
132 if (field_mask & SND_LARGEENTITY)
134 ent = (unsigned short) MSG_ReadShort ();
135 channel = MSG_ReadByte ();
139 channel = (unsigned short) MSG_ReadShort ();
144 if (largesoundindex || field_mask & SND_LARGESOUND)
145 sound_num = (unsigned short) MSG_ReadShort ();
147 sound_num = MSG_ReadByte ();
149 if (sound_num >= MAX_SOUNDS)
150 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
153 if (ent >= MAX_EDICTS)
154 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
156 for (i = 0;i < 3;i++)
157 pos[i] = MSG_ReadCoord ();
159 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
166 When the client is taking a long time to load stuff, send keepalive messages
167 so the server doesn't disconnect.
171 static qbyte olddata[NET_MAXMESSAGE];
172 void CL_KeepaliveMessage (void)
175 static float lastmsg;
180 // no need if server is local and definitely not if this is a demo
181 if (sv.active || cls.demoplayback)
184 // read messages from server, should just be nops
185 oldreadcount = msg_readcount;
186 oldbadread = msg_badread;
188 memcpy(olddata, net_message.data, net_message.cursize);
190 NetConn_ClientFrame();
192 msg_readcount = oldreadcount;
193 msg_badread = oldbadread;
195 memcpy(net_message.data, olddata, net_message.cursize);
197 if (cls.netcon && NetConn_CanSendMessage(cls.netcon) && (time = Sys_DoubleTime()) - lastmsg >= 5)
203 // LordHavoc: must use unreliable because reliable could kill the sigon message!
204 Con_Printf("--> client to server keepalive\n");
206 msg.maxsize = sizeof(buf);
208 MSG_WriteChar(&msg, svc_nop);
209 NetConn_SendUnreliableMessage(cls.netcon, &msg);
210 // try not to utterly crush the computer with work, that's just rude
215 void CL_ParseEntityLump(char *entdata)
218 char key[128], value[4096];
219 FOG_clear(); // LordHavoc: no fog until set
220 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
224 if (!COM_ParseToken(&data))
226 if (com_token[0] != '{')
230 if (!COM_ParseToken(&data))
232 if (com_token[0] == '}')
233 break; // end of worldspawn
234 if (com_token[0] == '_')
235 strcpy(key, com_token + 1);
237 strcpy(key, com_token);
238 while (key[strlen(key)-1] == ' ') // remove trailing spaces
239 key[strlen(key)-1] = 0;
240 if (!COM_ParseToken(&data))
242 strcpy(value, com_token);
243 if (!strcmp("sky", key))
245 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
247 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
249 else if (!strcmp("fog", key))
250 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
251 else if (!strcmp("fog_density", key))
252 fog_density = atof(value);
253 else if (!strcmp("fog_red", key))
254 fog_red = atof(value);
255 else if (!strcmp("fog_green", key))
256 fog_green = atof(value);
257 else if (!strcmp("fog_blue", key))
258 fog_blue = atof(value);
263 =====================
266 An svc_signonnum has been received, perform a client side setup
267 =====================
269 static void CL_SignonReply (void)
273 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
278 MSG_WriteByte (&cls.message, clc_stringcmd);
279 MSG_WriteString (&cls.message, "prespawn");
283 MSG_WriteByte (&cls.message, clc_stringcmd);
284 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
286 MSG_WriteByte (&cls.message, clc_stringcmd);
287 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
289 if (cl_pmodel.integer)
291 MSG_WriteByte (&cls.message, clc_stringcmd);
292 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
295 MSG_WriteByte (&cls.message, clc_stringcmd);
296 MSG_WriteString (&cls.message, "spawn");
300 MSG_WriteByte (&cls.message, clc_stringcmd);
301 MSG_WriteString (&cls.message, "begin");
315 qbyte entlife[MAX_EDICTS];
316 // FIXME: this is a lot of memory to be keeping around, this needs to be dynamically allocated and freed
317 static char parse_model_precache[MAX_MODELS][MAX_QPATH];
318 static char parse_sound_precache[MAX_SOUNDS][MAX_QPATH];
319 void CL_ParseServerInfo (void)
323 int nummodels, numsounds;
326 Con_DPrintf ("Serverinfo packet received.\n");
328 // wipe the client_state_t struct
332 // parse protocol version number
334 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
336 Host_Error ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
339 Nehahrademcompatibility = false;
341 Nehahrademcompatibility = true;
342 if (cls.demoplayback && demo_nehahra.integer)
343 Nehahrademcompatibility = true;
345 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
349 cl.maxclients = MSG_ReadByte ();
350 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
352 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
355 Mem_EmptyPool(cl_scores_mempool);
356 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
359 cl.gametype = MSG_ReadByte ();
361 // parse signon message
362 str = MSG_ReadString ();
363 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
365 // seperate the printfs so the server message can have a color
366 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
368 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");
369 Con_Printf ("%c%s\n", 2, str);
372 // check memory integrity
373 Mem_CheckSentinelsGlobal();
375 // disable until we get textures for it
378 memset(cl.model_precache, 0, sizeof(cl.model_precache));
379 memset(cl.sound_precache, 0, sizeof(cl.sound_precache));
381 // parse model precache list
382 for (nummodels=1 ; ; nummodels++)
384 str = MSG_ReadString();
387 if (nummodels==MAX_MODELS)
388 Host_Error ("Server sent too many model precaches\n");
389 if (strlen(str) >= MAX_QPATH)
390 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
391 strcpy(parse_model_precache[nummodels], str);
393 // parse sound precache list
394 for (numsounds=1 ; ; numsounds++)
396 str = MSG_ReadString();
399 if (numsounds==MAX_SOUNDS)
400 Host_Error("Server sent too many sound precaches\n");
401 if (strlen(str) >= MAX_QPATH)
402 Host_Error("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
403 strcpy(parse_sound_precache[numsounds], str);
406 // touch all of the precached models that are still loaded so we can free
407 // anything that isn't needed
409 for (i = 1;i < nummodels;i++)
411 CL_KeepaliveMessage();
412 Mod_TouchModel(parse_model_precache[i]);
414 // do the same for sounds
415 for (i = 1;i < numsounds;i++)
417 CL_KeepaliveMessage();
418 S_TouchSound(parse_sound_precache[i]);
420 // purge anything that was not touched
423 // now we try to load everything that is new
426 CL_KeepaliveMessage ();
427 cl.model_precache[1] = Mod_ForName(parse_model_precache[1], false, false, true);
428 if (cl.model_precache[1] == NULL)
429 Con_Printf("Map %s not found\n", parse_model_precache[1]);
432 for (i=2 ; i<nummodels ; i++)
434 CL_KeepaliveMessage();
435 if ((cl.model_precache[i] = Mod_ForName(parse_model_precache[i], false, false, false)) == NULL)
436 Con_Printf("Model %s not found\n", parse_model_precache[i]);
440 S_BeginPrecaching ();
441 for (i=1 ; i<numsounds ; i++)
443 CL_KeepaliveMessage();
444 cl.sound_precache[i] = S_PrecacheSound(parse_sound_precache[i], true);
449 ent = &cl_entities[0];
450 // entire entity array was cleared, so just fill in a few fields
451 ent->state_current.active = true;
452 ent->render.model = cl.worldmodel = cl.model_precache[1];
453 //ent->render.scale = 1;
454 ent->render.alpha = 1;
455 ent->render.flags = RENDER_SHADOW;
456 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
457 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
458 CL_BoundingBoxForEntity(&ent->render);
459 // clear entlife array
460 memset(entlife, 0, MAX_EDICTS);
467 // noclip is turned off at start
468 noclip_anglehack = false;
470 // check memory integrity
471 Mem_CheckSentinelsGlobal();
474 void CL_ValidateState(entity_state_t *s)
481 if (s->modelindex >= MAX_MODELS)
482 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
484 // colormap is client index + 1
485 if (s->colormap > cl.maxclients)
486 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
488 model = cl.model_precache[s->modelindex];
489 Mod_CheckLoaded(model);
490 if (model && s->frame >= model->numframes)
492 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
495 if (model && s->skin > 0 && s->skin >= model->numskins)
497 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
502 void CL_MoveLerpEntityStates(entity_t *ent)
504 float odelta[3], adelta[3];
505 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
506 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
507 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
509 // we definitely shouldn't lerp
510 ent->persistent.lerpdeltatime = 0;
511 ent->persistent.lerpstarttime = cl.mtime[1];
512 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
513 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
514 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
515 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
517 else if (ent->state_current.flags & RENDER_STEP)
519 // monster interpolation
520 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
522 ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
523 ent->persistent.lerpstarttime = cl.mtime[1];
524 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
525 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
526 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
527 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
533 ent->persistent.lerpstarttime = cl.mtime[1];
534 // no lerp if it's singleplayer
535 if (sv.active && svs.maxclients == 1)
536 ent->persistent.lerpdeltatime = 0;
538 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
539 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
540 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
541 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
542 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
550 Parse an entity update message from the server
551 If an entities model or origin changes from frame to frame, it must be
552 relinked. Other attributes can change without relinking.
555 void CL_ParseUpdate (int bits)
561 if (bits & U_MOREBITS)
562 bits |= (MSG_ReadByte()<<8);
563 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
565 bits |= MSG_ReadByte() << 16;
566 if (bits & U_EXTEND2)
567 bits |= MSG_ReadByte() << 24;
570 if (bits & U_LONGENTITY)
571 num = (unsigned) MSG_ReadShort ();
573 num = (unsigned) MSG_ReadByte ();
575 if (num >= MAX_EDICTS)
576 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
578 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
580 ent = cl_entities + num;
582 // note: this inherits the 'active' state of the baseline chosen
583 // (state_baseline is always active, state_current may not be active if
584 // the entity was missing in the last frame)
586 new = ent->state_current;
589 new = ent->state_baseline;
594 new.time = cl.mtime[0];
596 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
597 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
598 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
599 if (bits & U_SKIN) new.skin = MSG_ReadByte();
600 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
601 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
602 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
603 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
604 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
605 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
606 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
607 if (bits & U_STEP) new.flags |= RENDER_STEP;
608 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
609 if (bits & U_SCALE) new.scale = MSG_ReadByte();
610 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
611 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
612 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
613 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
614 if (bits & U_COLORMOD) MSG_ReadByte();
615 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
616 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
617 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
618 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
619 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
621 // LordHavoc: to allow playback of the Nehahra movie
622 if (Nehahrademcompatibility && (bits & U_EXTEND1))
624 // LordHavoc: evil format
625 int i = MSG_ReadFloat();
626 int j = MSG_ReadFloat() * 255.0f;
631 new.effects |= EF_FULLBRIGHT;
635 else if (j == 0 || j >= 255)
642 CL_ValidateState(&new);
644 ent->state_previous = ent->state_current;
645 ent->state_current = new;
646 if (ent->state_current.active)
648 CL_MoveLerpEntityStates(ent);
649 cl_entities_active[ent->state_current.number] = true;
650 // mark as visible (no kill this frame)
651 entlife[ent->state_current.number] = 2;
655 static entity_frame_t entityframe;
656 void CL_ReadEntityFrame(void)
660 EntityFrame_Read(&cl.entitydatabase);
661 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
662 for (i = 0;i < entityframe.numentities;i++)
665 ent = &cl_entities[entityframe.entitydata[i].number];
666 ent->state_previous = ent->state_current;
667 ent->state_current = entityframe.entitydata[i];
668 CL_MoveLerpEntityStates(ent);
669 // the entity lives again...
670 entlife[ent->state_current.number] = 2;
671 cl_entities_active[ent->state_current.number] = true;
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 CL_FindNonSolidLocation(pos, pos, 4);
1012 CL_AllocDlight(NULL, pos, 50, 0.25f, 1.00f, 0.25f, 250, 0.2);
1013 CL_RunParticleEffect(pos, vec3_origin, 20, 30);
1014 S_StartSound(-1, 0, cl_sfx_wizhit, pos, 1, 1);
1017 case TE_KNIGHTSPIKE:
1018 // spike hitting wall
1019 MSG_ReadVector(pos);
1020 CL_FindNonSolidLocation(pos, pos, 4);
1021 CL_AllocDlight(NULL, pos, 50, 1.0f, 0.60f, 0.20f, 250, 0.2);
1022 CL_RunParticleEffect(pos, vec3_origin, 226, 20);
1023 S_StartSound(-1, 0, cl_sfx_knighthit, pos, 1, 1);
1027 // spike hitting wall
1028 MSG_ReadVector(pos);
1029 CL_FindNonSolidLocation(pos, pos, 4);
1030 // LordHavoc: changed to spark shower
1031 CL_SparkShower(pos, vec3_origin, 15);
1033 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1038 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1040 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1042 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1046 // quad spike hitting wall
1047 MSG_ReadVector(pos);
1048 CL_FindNonSolidLocation(pos, pos, 4);
1049 // LordHavoc: changed to spark shower
1050 CL_SparkShower(pos, vec3_origin, 15);
1051 CL_AllocDlight(NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1052 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1054 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1059 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1061 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1063 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1067 // super spike hitting wall
1068 MSG_ReadVector(pos);
1069 CL_FindNonSolidLocation(pos, pos, 4);
1070 // LordHavoc: changed to dust shower
1071 CL_SparkShower(pos, vec3_origin, 30);
1073 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1078 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1080 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1082 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1085 case TE_SUPERSPIKEQUAD:
1086 // quad super spike hitting wall
1087 MSG_ReadVector(pos);
1088 CL_FindNonSolidLocation(pos, pos, 4);
1089 // LordHavoc: changed to dust shower
1090 CL_SparkShower(pos, vec3_origin, 30);
1091 CL_AllocDlight(NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1093 S_StartSound(-1, 0, cl_sfx_tink1, pos, 1, 1);
1098 S_StartSound(-1, 0, cl_sfx_ric1, pos, 1, 1);
1100 S_StartSound(-1, 0, cl_sfx_ric2, pos, 1, 1);
1102 S_StartSound(-1, 0, cl_sfx_ric3, pos, 1, 1);
1105 // LordHavoc: added for improved blood splatters
1108 MSG_ReadVector(pos);
1109 CL_FindNonSolidLocation(pos, pos, 4);
1110 dir[0] = MSG_ReadChar();
1111 dir[1] = MSG_ReadChar();
1112 dir[2] = MSG_ReadChar();
1113 count = MSG_ReadByte();
1114 CL_BloodPuff(pos, dir, count);
1118 MSG_ReadVector(pos);
1119 CL_FindNonSolidLocation(pos, pos, 4);
1120 CL_BloodPuff(pos, vec3_origin, 10);
1124 MSG_ReadVector(pos);
1125 CL_FindNonSolidLocation(pos, pos, 4);
1126 dir[0] = MSG_ReadChar();
1127 dir[1] = MSG_ReadChar();
1128 dir[2] = MSG_ReadChar();
1129 count = MSG_ReadByte();
1130 CL_SparkShower(pos, dir, count);
1133 MSG_ReadVector(pos);
1134 CL_FindNonSolidLocation(pos, pos, 4);
1135 CL_AllocDlight(NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1138 // LordHavoc: added for improved gore
1139 case TE_BLOODSHOWER:
1141 MSG_ReadVector(pos); // mins
1142 MSG_ReadVector(pos2); // maxs
1143 velspeed = MSG_ReadCoord(); // speed
1144 count = MSG_ReadShort(); // number of particles
1145 CL_BloodShower(pos, pos2, velspeed, count);
1147 case TE_PARTICLECUBE:
1148 // general purpose particle effect
1149 MSG_ReadVector(pos); // mins
1150 MSG_ReadVector(pos2); // maxs
1151 MSG_ReadVector(dir); // dir
1152 count = MSG_ReadShort(); // number of particles
1153 colorStart = MSG_ReadByte(); // color
1154 colorLength = MSG_ReadByte(); // gravity (1 or 0)
1155 velspeed = MSG_ReadCoord(); // randomvel
1156 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1159 case TE_PARTICLERAIN:
1160 // general purpose particle effect
1161 MSG_ReadVector(pos); // mins
1162 MSG_ReadVector(pos2); // maxs
1163 MSG_ReadVector(dir); // dir
1164 count = MSG_ReadShort(); // number of particles
1165 colorStart = MSG_ReadByte(); // color
1166 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1169 case TE_PARTICLESNOW:
1170 // general purpose particle effect
1171 MSG_ReadVector(pos); // mins
1172 MSG_ReadVector(pos2); // maxs
1173 MSG_ReadVector(dir); // dir
1174 count = MSG_ReadShort(); // number of particles
1175 colorStart = MSG_ReadByte(); // color
1176 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1180 // bullet hitting wall
1181 MSG_ReadVector(pos);
1182 CL_FindNonSolidLocation(pos, pos, 4);
1183 // LordHavoc: changed to dust shower
1184 CL_SparkShower(pos, vec3_origin, 15);
1187 case TE_GUNSHOTQUAD:
1188 // quad bullet hitting wall
1189 MSG_ReadVector(pos);
1190 CL_FindNonSolidLocation(pos, pos, 4);
1191 CL_SparkShower(pos, vec3_origin, 15);
1192 CL_AllocDlight(NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1197 MSG_ReadVector(pos);
1198 CL_FindNonSolidLocation(pos, pos, 10);
1199 CL_ParticleExplosion(pos);
1200 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1201 CL_AllocDlight(NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1202 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1205 case TE_EXPLOSIONQUAD:
1206 // quad rocket explosion
1207 MSG_ReadVector(pos);
1208 CL_FindNonSolidLocation(pos, pos, 10);
1209 CL_ParticleExplosion(pos);
1210 CL_AllocDlight(NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1211 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1215 // Nehahra movie colored lighting explosion
1216 MSG_ReadVector(pos);
1217 CL_FindNonSolidLocation(pos, pos, 10);
1218 CL_ParticleExplosion(pos);
1219 CL_AllocDlight(NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1220 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1223 case TE_EXPLOSIONRGB:
1224 // colored lighting explosion
1225 MSG_ReadVector(pos);
1226 CL_FindNonSolidLocation(pos, pos, 10);
1227 CL_ParticleExplosion(pos);
1228 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1229 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1230 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1231 CL_AllocDlight(NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1232 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1235 case TE_TAREXPLOSION:
1236 // tarbaby explosion
1237 MSG_ReadVector(pos);
1238 CL_FindNonSolidLocation(pos, pos, 10);
1239 CL_BlobExplosion(pos);
1241 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
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);
1247 MSG_ReadVector(pos);
1248 CL_FindNonSolidLocation(pos, pos, 10);
1249 CL_AllocDlight(NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1252 case TE_CUSTOMFLASH:
1253 MSG_ReadVector(pos);
1254 CL_FindNonSolidLocation(pos, pos, 4);
1255 radius = MSG_ReadByte() * 8;
1256 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1257 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1258 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1259 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1260 CL_AllocDlight(NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1264 MSG_ReadVector(pos);
1265 MSG_ReadVector(dir);
1266 count = MSG_ReadByte();
1267 CL_Flames(pos, dir, count);
1273 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1274 CL_ParseBeam(cl_model_bolt, true);
1279 if (!cl_model_bolt2)
1280 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1281 CL_ParseBeam(cl_model_bolt2, true);
1286 if (!cl_model_bolt3)
1287 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1288 CL_ParseBeam(cl_model_bolt3, false);
1293 // grappling hook beam
1295 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1296 CL_ParseBeam(cl_model_beam, false);
1300 // LordHavoc: for compatibility with the Nehahra movie...
1301 case TE_LIGHTNING4NEH:
1302 CL_ParseBeam(Mod_ForName(MSG_ReadString(), true, false, false), false);
1306 pos[0] = MSG_ReadCoord();
1307 pos[1] = MSG_ReadCoord();
1308 pos[2] = MSG_ReadCoord();
1313 pos[0] = MSG_ReadCoord();
1314 pos[1] = MSG_ReadCoord();
1315 pos[2] = MSG_ReadCoord();
1316 CL_AllocDlight(NULL, pos, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f);
1317 // CL_TeleportSplash(pos);
1321 // color mapped explosion
1322 MSG_ReadVector(pos);
1323 CL_FindNonSolidLocation(pos, pos, 10);
1324 colorStart = MSG_ReadByte();
1325 colorLength = MSG_ReadByte();
1326 CL_ParticleExplosion2(pos, colorStart, colorLength);
1327 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1328 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);
1329 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1333 MSG_ReadVector(pos);
1334 MSG_ReadVector(pos2);
1335 MSG_ReadVector(dir);
1336 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1337 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1341 MSG_ReadVector(pos);
1342 MSG_ReadVector(dir);
1343 count = MSG_ReadByte();
1344 CL_FindNonSolidLocation(pos, pos, 4);
1345 CL_Tei_Smoke(pos, dir, count);
1348 case TE_TEI_BIGEXPLOSION:
1349 MSG_ReadVector(pos);
1350 CL_FindNonSolidLocation(pos, pos, 10);
1351 CL_ParticleExplosion(pos);
1352 CL_AllocDlight(NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
1353 S_StartSound(-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1356 case TE_TEI_PLASMAHIT:
1357 MSG_ReadVector(pos);
1358 MSG_ReadVector(dir);
1359 count = MSG_ReadByte();
1360 CL_FindNonSolidLocation(pos, pos, 5);
1361 CL_Tei_PlasmaHit(pos, dir, count);
1362 CL_AllocDlight(NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
1366 Host_Error("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1370 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1372 static qbyte cgamenetbuffer[65536];
1375 =====================
1376 CL_ParseServerMessage
1377 =====================
1379 int parsingerror = false;
1380 void CL_ParseServerMessage(void)
1383 int i, entitiesupdated;
1385 char *cmdlogname[32], *temp;
1386 int cmdindex, cmdcount = 0;
1388 if (cls.demorecording)
1389 CL_WriteDemoMessage ();
1391 cl.last_received_message = realtime;
1394 // if recording demos, copy the message out
1396 if (cl_shownet.integer == 1)
1397 Con_Printf ("%f %i\n", realtime, net_message.cursize);
1398 else if (cl_shownet.integer == 2)
1399 Con_Printf ("------------------\n");
1401 cl.onground = false; // unless the server says otherwise
1403 // parse the message
1405 //MSG_BeginReading ();
1407 entitiesupdated = false;
1409 parsingerror = true;
1414 Host_Error ("CL_ParseServerMessage: Bad server message");
1416 cmd = MSG_ReadByte ();
1420 SHOWNET("END OF MESSAGE");
1421 break; // end of message
1424 cmdindex = cmdcount & 31;
1426 cmdlog[cmdindex] = cmd;
1428 // if the high bit of the command byte is set, it is a fast update
1431 // 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)
1433 cmdlogname[cmdindex] = temp;
1434 SHOWNET("fast update");
1435 if (cls.signon == SIGNONS - 1)
1437 // first update is the final signon stage
1438 cls.signon = SIGNONS;
1441 CL_ParseUpdate (cmd&127);
1445 SHOWNET(svc_strings[cmd]);
1446 cmdlogname[cmdindex] = svc_strings[cmd];
1447 if (!cmdlogname[cmdindex])
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)
1451 cmdlogname[cmdindex] = temp;
1459 char description[32*64], temp[64];
1461 strcpy(description, "packet dump: ");
1465 count = cmdcount - i;
1469 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1470 strcat(description, temp);
1475 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1476 Con_Printf("%s", description);
1477 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1482 if (cls.signon < SIGNONS)
1483 Con_Printf("<-- server to client keepalive\n");
1487 if (!entitiesupdated)
1489 // this is a new frame, we'll be seeing entities,
1490 // so prepare for entity updates
1491 CL_EntityUpdateSetup();
1492 entitiesupdated = true;
1494 cl.mtime[1] = cl.mtime[0];
1495 cl.mtime[0] = MSG_ReadFloat ();
1498 case svc_clientdata:
1499 i = MSG_ReadShort ();
1500 CL_ParseClientdata (i);
1504 i = MSG_ReadLong ();
1505 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1506 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1507 Nehahrademcompatibility = false;
1509 Nehahrademcompatibility = true;
1510 if (cls.demoplayback && demo_nehahra.integer)
1511 Nehahrademcompatibility = true;
1513 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1517 case svc_disconnect:
1518 Host_EndGame ("Server disconnected\n");
1521 Con_Printf ("%s", MSG_ReadString ());
1524 case svc_centerprint:
1525 SCR_CenterPrint (MSG_ReadString ());
1529 Cbuf_AddText (MSG_ReadString ());
1536 case svc_serverinfo:
1537 CL_ParseServerInfo ();
1541 for (i=0 ; i<3 ; i++)
1542 cl.viewangles[i] = MSG_ReadAngle ();
1546 cl.viewentity = (unsigned short)MSG_ReadShort ();
1547 if (cl.viewentity >= MAX_EDICTS)
1548 Host_Error("svc_setview >= MAX_EDICTS\n");
1549 // LordHavoc: assume first setview recieved is the real player entity
1550 if (!cl.playerentity)
1551 cl.playerentity = cl.viewentity;
1554 case svc_lightstyle:
1555 i = MSG_ReadByte ();
1556 if (i >= MAX_LIGHTSTYLES)
1557 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1558 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1559 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1560 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1564 CL_ParseStartSoundPacket(false);
1568 CL_ParseStartSoundPacket(true);
1572 i = MSG_ReadShort();
1573 S_StopSound(i>>3, i&7);
1576 case svc_updatename:
1577 i = MSG_ReadByte ();
1578 if (i >= cl.maxclients)
1579 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1580 strcpy (cl.scores[i].name, MSG_ReadString ());
1583 case svc_updatefrags:
1584 i = MSG_ReadByte ();
1585 if (i >= cl.maxclients)
1586 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1587 cl.scores[i].frags = MSG_ReadShort ();
1590 case svc_updatecolors:
1591 i = MSG_ReadByte ();
1592 if (i >= cl.maxclients)
1593 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1594 cl.scores[i].colors = MSG_ReadByte ();
1598 CL_ParseParticleEffect ();
1609 case svc_spawnbaseline:
1610 i = MSG_ReadShort ();
1611 if (i < 0 || i >= MAX_EDICTS)
1612 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1613 CL_ParseBaseline (cl_entities + i, false);
1615 case svc_spawnbaseline2:
1616 i = MSG_ReadShort ();
1617 if (i < 0 || i >= MAX_EDICTS)
1618 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1619 CL_ParseBaseline (cl_entities + i, true);
1621 case svc_spawnstatic:
1622 CL_ParseStatic (false);
1624 case svc_spawnstatic2:
1625 CL_ParseStatic (true);
1627 case svc_temp_entity:
1628 CL_ParseTempEntity ();
1632 cl.paused = MSG_ReadByte ();
1640 i = MSG_ReadByte ();
1641 if (i <= cls.signon)
1642 Host_Error ("Received signon %i when at %i", i, cls.signon);
1647 case svc_killedmonster:
1648 cl.stats[STAT_MONSTERS]++;
1651 case svc_foundsecret:
1652 cl.stats[STAT_SECRETS]++;
1655 case svc_updatestat:
1656 i = MSG_ReadByte ();
1657 if (i < 0 || i >= MAX_CL_STATS)
1658 Host_Error ("svc_updatestat: %i is invalid", i);
1659 cl.stats[i] = MSG_ReadLong ();
1662 case svc_spawnstaticsound:
1663 CL_ParseStaticSound (false);
1666 case svc_spawnstaticsound2:
1667 CL_ParseStaticSound (true);
1671 cl.cdtrack = MSG_ReadByte ();
1672 cl.looptrack = MSG_ReadByte ();
1673 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1674 CDAudio_Play ((qbyte)cls.forcetrack, true);
1676 CDAudio_Play ((qbyte)cl.cdtrack, true);
1679 case svc_intermission:
1680 cl.intermission = 1;
1681 cl.completed_time = cl.time;
1685 cl.intermission = 2;
1686 cl.completed_time = cl.time;
1687 SCR_CenterPrint (MSG_ReadString ());
1691 cl.intermission = 3;
1692 cl.completed_time = cl.time;
1693 SCR_CenterPrint (MSG_ReadString ());
1696 case svc_sellscreen:
1697 Cmd_ExecuteString ("help", src_command);
1700 SHOWLMP_decodehide();
1703 SHOWLMP_decodeshow();
1706 R_SetSkyBox(MSG_ReadString());
1711 length = (int) ((unsigned short) MSG_ReadShort());
1712 for (i = 0;i < length;i++)
1713 cgamenetbuffer[i] = MSG_ReadByte();
1715 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1719 if (cls.signon == SIGNONS - 1)
1721 // first update is the final signon stage
1722 cls.signon = SIGNONS;
1725 CL_ReadEntityFrame();
1730 if (entitiesupdated)
1731 CL_EntityUpdateEnd();
1733 parsingerror = false;
1736 void CL_Parse_DumpPacket(void)
1740 Con_Printf("Packet dump:\n");
1741 SZ_HexDumpToConsole(&net_message);
1742 parsingerror = false;
1745 void CL_Parse_Init(void)
1747 // LordHavoc: added demo_nehahra cvar
1748 cl_scores_mempool = Mem_AllocPool("client player info");
1749 Cvar_RegisterVariable (&demo_nehahra);
1750 if (gamemode == GAME_NEHAHRA)
1751 Cvar_SetValue("demo_nehahra", 1);