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 void CL_Parse_Init(void)
101 // LordHavoc: added demo_nehahra cvar
102 Cvar_RegisterVariable (&demo_nehahra);
103 if (gamemode == GAME_NEHAHRA)
104 Cvar_SetValue("demo_nehahra", 1);
107 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
108 int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces
114 This error checks and tracks the total number of entities
117 entity_t *CL_EntityNum (int num)
119 if (num >= MAX_EDICTS)
120 Host_Error ("CL_EntityNum: %i is an invalid number",num);
122 return &cl_entities[num];
128 CL_ParseStartSoundPacket
131 void CL_ParseStartSoundPacket(int largesoundindex)
141 field_mask = MSG_ReadByte();
143 if (field_mask & SND_VOLUME)
144 volume = MSG_ReadByte ();
146 volume = DEFAULT_SOUND_PACKET_VOLUME;
148 if (field_mask & SND_ATTENUATION)
149 attenuation = MSG_ReadByte () / 64.0;
151 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
153 channel = MSG_ReadShort ();
155 sound_num = (unsigned short) MSG_ReadShort ();
157 sound_num = MSG_ReadByte ();
159 if (sound_num >= MAX_SOUNDS)
160 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
165 if (ent > MAX_EDICTS)
166 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
168 for (i=0 ; i<3 ; i++)
169 pos[i] = MSG_ReadCoord ();
171 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
178 When the client is taking a long time to load stuff, send keepalive messages
179 so the server doesn't disconnect.
182 void CL_KeepaliveMessage (void)
185 static float lastmsg;
192 return; // no need if server is local
193 if (cls.demoplayback)
196 // read messages from server, should just be nops
198 memcpy (olddata, net_message.data, net_message.cursize);
202 ret = CL_GetMessage ();
206 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
208 break; // nothing waiting
210 Host_Error ("CL_KeepaliveMessage: received a message");
215 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
221 memcpy (net_message.data, olddata, net_message.cursize);
224 time = Sys_DoubleTime ();
225 if (time - lastmsg < 5)
230 Con_Printf ("--> client to server keepalive\n");
232 MSG_WriteByte (&cls.message, clc_nop);
233 NET_SendMessage (cls.netcon, &cls.message);
234 SZ_Clear (&cls.message);
237 void CL_ParseEntityLump(char *entdata)
240 char key[128], value[4096];
241 FOG_clear(); // LordHavoc: no fog until set
242 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
246 data = COM_Parse(data);
249 if (com_token[0] != '{')
253 data = COM_Parse(data);
256 if (com_token[0] == '}')
257 break; // end of worldspawn
258 if (com_token[0] == '_')
259 strcpy(key, com_token + 1);
261 strcpy(key, com_token);
262 while (key[strlen(key)-1] == ' ') // remove trailing spaces
263 key[strlen(key)-1] = 0;
264 data = COM_Parse(data);
267 strcpy(value, com_token);
268 if (!strcmp("sky", key))
270 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
272 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
274 else if (!strcmp("fog", key))
275 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
276 else if (!strcmp("fog_density", key))
277 fog_density = atof(value);
278 else if (!strcmp("fog_red", key))
279 fog_red = atof(value);
280 else if (!strcmp("fog_green", key))
281 fog_green = atof(value);
282 else if (!strcmp("fog_blue", key))
283 fog_blue = atof(value);
288 =====================
291 An svc_signonnum has been received, perform a client side setup
292 =====================
294 static void CL_SignonReply (void)
298 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
303 MSG_WriteByte (&cls.message, clc_stringcmd);
304 MSG_WriteString (&cls.message, "prespawn");
308 MSG_WriteByte (&cls.message, clc_stringcmd);
309 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
311 MSG_WriteByte (&cls.message, clc_stringcmd);
312 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
314 if (cl_pmodel.integer)
316 MSG_WriteByte (&cls.message, clc_stringcmd);
317 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
320 MSG_WriteByte (&cls.message, clc_stringcmd);
321 sprintf (str, "spawn %s", cls.spawnparms);
322 MSG_WriteString (&cls.message, str);
326 MSG_WriteByte (&cls.message, clc_stringcmd);
327 MSG_WriteString (&cls.message, "begin");
341 void CL_ParseServerInfo (void)
345 int nummodels, numsounds;
346 char model_precache[MAX_MODELS][MAX_QPATH];
347 char sound_precache[MAX_SOUNDS][MAX_QPATH];
349 Con_DPrintf ("Serverinfo packet received.\n");
351 // wipe the client_state_t struct
355 // parse protocol version number
357 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
359 Con_Printf ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
362 Nehahrademcompatibility = false;
364 Nehahrademcompatibility = true;
365 if (cls.demoplayback && demo_nehahra.integer)
366 Nehahrademcompatibility = true;
368 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
372 cl.maxclients = MSG_ReadByte ();
373 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
375 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
378 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
381 cl.gametype = MSG_ReadByte ();
383 // parse signon message
384 str = MSG_ReadString ();
385 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
387 // seperate the printfs so the server message can have a color
388 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
390 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");
391 Con_Printf ("%c%s\n", 2, str);
395 // first we go through and touch all of the precache data that still
396 // happens to be in the cache, so precaching something else doesn't
397 // needlessly purge it
400 Mem_CheckSentinelsGlobal();
405 memset (cl.model_precache, 0, sizeof(cl.model_precache));
406 for (nummodels=1 ; ; nummodels++)
408 str = MSG_ReadString ();
411 if (nummodels==MAX_MODELS)
413 Host_Error ("Server sent too many model precaches\n");
416 if (strlen(str) >= MAX_QPATH)
417 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
418 strcpy (model_precache[nummodels], str);
419 Mod_TouchModel (str);
423 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
424 for (numsounds=1 ; ; numsounds++)
426 str = MSG_ReadString ();
429 if (numsounds==MAX_SOUNDS)
431 Host_Error ("Server sent too many sound precaches\n");
434 if (strlen(str) >= MAX_QPATH)
435 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
436 strcpy (sound_precache[numsounds], str);
443 // now we try to load everything else until a cache allocation fails
446 for (i=1 ; i<nummodels ; i++)
448 // LordHavoc: i == 1 means the first model is the world model
449 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
451 if (cl.model_precache[i] == NULL)
453 Host_Error("Model %s not found\n", model_precache[i]);
456 CL_KeepaliveMessage ();
459 S_BeginPrecaching ();
460 for (i=1 ; i<numsounds ; i++)
462 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
463 CL_KeepaliveMessage ();
468 cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
469 cl_entities[0].render.scale = 1;
470 cl_entities[0].render.alpha = 1;
476 Mem_CheckSentinelsGlobal();
478 noclip_anglehack = false; // noclip is turned off at start
481 void CL_ValidateState(entity_state_t *s)
488 if (s->modelindex >= MAX_MODELS)
489 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
491 // colormap is client index + 1
492 if (s->colormap > cl.maxclients)
493 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
495 model = cl.model_precache[s->modelindex];
496 Mod_CheckLoaded(model);
497 if (model && s->frame >= model->numframes)
499 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
502 if (model && s->skin > 0 && s->skin >= model->numskins)
504 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
513 Parse an entity update message from the server
514 If an entities model or origin changes from frame to frame, it must be
515 relinked. Other attributes can change without relinking.
518 qbyte entkill[MAX_EDICTS];
519 int bitprofile[32], bitprofilecount = 0;
520 void CL_ParseUpdate (int bits)
522 int i, num, deltadie;
526 if (bits & U_MOREBITS)
527 bits |= (MSG_ReadByte()<<8);
528 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
530 bits |= MSG_ReadByte() << 16;
531 if (bits & U_EXTEND2)
532 bits |= MSG_ReadByte() << 24;
535 if (bits & U_LONGENTITY)
536 num = (unsigned) MSG_ReadShort ();
538 num = (unsigned) MSG_ReadByte ();
540 if (num >= MAX_EDICTS)
541 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
543 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
545 // mark as visible (no kill)
548 ent = CL_EntityNum (num);
550 for (i = 0;i < 32;i++)
558 new = ent->state_current;
560 deltadie = true; // was not present in previous frame, leave hidden until next full update
563 new = ent->state_baseline;
565 new.time = cl.mtime[0];
569 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
570 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
571 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
572 if (bits & U_SKIN) new.skin = MSG_ReadByte();
573 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
574 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
575 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
576 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
577 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
578 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
579 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
580 if (bits & U_STEP) new.flags |= RENDER_STEP;
581 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
582 if (bits & U_SCALE) new.scale = MSG_ReadByte();
583 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
584 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
585 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
586 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
587 if (bits & U_COLORMOD) MSG_ReadByte();
588 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
589 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
590 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
591 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
592 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
594 // LordHavoc: to allow playback of the Nehahra movie
595 if (Nehahrademcompatibility && (bits & U_EXTEND1))
597 // LordHavoc: evil format
598 int i = MSG_ReadFloat();
599 int j = MSG_ReadFloat() * 255.0f;
604 new.effects |= EF_FULLBRIGHT;
608 else if (j == 0 || j >= 255)
620 CL_ValidateState(&new);
622 if (new.flags & RENDER_STEP) // FIXME: rename this flag?
624 // make time identical for memcmp
625 new.time = ent->state_current.time;
626 if (memcmp(&new, &ent->state_current, sizeof(entity_state_t)))
628 // set it back to what it should be
629 new.time = cl.mtime[0] + 0.1;
631 ent->state_previous = ent->state_current;
632 ent->state_current = new;
633 // assume 10fps animation
634 //ent->state_previous.time = cl.mtime[0] - 0.1;
639 ent->state_previous = ent->state_current;
640 ent->state_current = new;
644 void CL_ReadEntityFrame(void)
648 entity_frame_t entityframe;
650 EntityFrame_Read(&cl.entitydatabase);
651 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
652 for (i = 0;i < entityframe.numentities;i++)
654 s = &entityframe.entitydata[i];
655 entkill[s->number] = 0;
656 ent = &cl_entities[s->number];
657 memcpy(&ent->state_previous, &ent->state_current, sizeof(*s));
658 memcpy(&ent->state_current, s, sizeof(*s));
659 ent->state_current.time = cl.mtime[0];
661 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
662 VectorCopy(entityframe.eye, cl.viewentoriginnew);
665 char *bitprofilenames[32] =
689 "obsolete U_COLORMOD",
701 void CL_BitProfile_f(void)
704 Con_Printf("bitprofile: %i updates\n");
706 for (i = 0;i < 32;i++)
707 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
709 for (i = 0;i < 32;i++)
714 void CL_EntityUpdateSetup(void)
716 memset(entkill, 1, MAX_EDICTS);
719 void CL_EntityUpdateEnd(void)
722 for (i = 1;i < MAX_EDICTS;i++)
724 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
732 void CL_ParseBaseline (entity_t *ent, int large)
736 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
737 ent->state_baseline.active = true;
740 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
741 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
745 ent->state_baseline.modelindex = MSG_ReadByte ();
746 ent->state_baseline.frame = MSG_ReadByte ();
748 ent->state_baseline.colormap = MSG_ReadByte();
749 ent->state_baseline.skin = MSG_ReadByte();
750 for (i = 0;i < 3;i++)
752 ent->state_baseline.origin[i] = MSG_ReadCoord ();
753 ent->state_baseline.angles[i] = MSG_ReadAngle ();
755 ent->state_baseline.alpha = 255;
756 ent->state_baseline.scale = 16;
757 ent->state_baseline.glowsize = 0;
758 ent->state_baseline.glowcolor = 254;
759 ent->state_previous = ent->state_current = ent->state_baseline;
761 CL_ValidateState(&ent->state_baseline);
769 Server information pertaining to this client only
772 void CL_ParseClientdata (int bits)
777 if (bits & SU_EXTEND1)
778 bits |= (MSG_ReadByte() << 16);
779 if (bits & SU_EXTEND2)
780 bits |= (MSG_ReadByte() << 24);
782 if (bits & SU_VIEWHEIGHT)
783 cl.viewheight = MSG_ReadChar ();
785 cl.viewheight = DEFAULT_VIEWHEIGHT;
787 if (bits & SU_IDEALPITCH)
788 cl.idealpitch = MSG_ReadChar ();
792 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
793 for (i=0 ; i<3 ; i++)
795 if (bits & (SU_PUNCH1<<i) )
798 cl.punchangle[i] = MSG_ReadPreciseAngle();
800 cl.punchangle[i] = MSG_ReadChar();
803 cl.punchangle[i] = 0;
804 if (bits & (SU_PUNCHVEC1<<i))
805 cl.punchvector[i] = MSG_ReadCoord();
807 cl.punchvector[i] = 0;
808 if (bits & (SU_VELOCITY1<<i) )
809 cl.mvelocity[0][i] = MSG_ReadChar()*16;
811 cl.mvelocity[0][i] = 0;
817 for (j=0 ; j<32 ; j++)
818 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
819 cl.item_gettime[j] = cl.time;
823 cl.onground = (bits & SU_ONGROUND) != 0;
824 cl.inwater = (bits & SU_INWATER) != 0;
826 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
827 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
828 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
829 cl.stats[STAT_HEALTH] = MSG_ReadShort();
830 cl.stats[STAT_AMMO] = MSG_ReadByte();
832 cl.stats[STAT_SHELLS] = MSG_ReadByte();
833 cl.stats[STAT_NAILS] = MSG_ReadByte();
834 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
835 cl.stats[STAT_CELLS] = MSG_ReadByte();
839 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
840 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
842 cl.stats[STAT_ACTIVEWEAPON] = i;
844 cl.viewzoomold = cl.viewzoomnew; // for interpolation
845 if (bits & SU_VIEWZOOM)
850 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
858 =====================
860 =====================
862 void CL_ParseStatic (int large)
866 if (cl.num_statics >= MAX_STATIC_ENTITIES)
867 Host_Error ("Too many static entities");
868 ent = &cl_static_entities[cl.num_statics++];
869 CL_ParseBaseline (ent, large);
871 // copy it to the current state
872 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
873 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
874 ent->render.framelerp = 0;
875 // make torchs play out of sync
876 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
877 ent->render.colormap = -1; // no special coloring
878 ent->render.skinnum = ent->state_baseline.skin;
879 ent->render.effects = ent->state_baseline.effects;
880 ent->render.alpha = 1;
881 ent->render.scale = 1;
882 ent->render.alpha = 1;
884 VectorCopy (ent->state_baseline.origin, ent->render.origin);
885 VectorCopy (ent->state_baseline.angles, ent->render.angles);
887 // This is definitely cheating...
888 if (ent->render.model == NULL)
897 void CL_ParseStaticSound (int large)
900 int sound_num, vol, atten;
904 sound_num = (unsigned short) MSG_ReadShort ();
906 sound_num = MSG_ReadByte ();
907 vol = MSG_ReadByte ();
908 atten = MSG_ReadByte ();
910 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
913 void CL_ParseEffect (void)
916 int modelindex, startframe, framecount, framerate;
919 modelindex = MSG_ReadByte ();
920 startframe = MSG_ReadByte ();
921 framecount = MSG_ReadByte ();
922 framerate = MSG_ReadByte ();
924 CL_Effect(org, modelindex, startframe, framecount, framerate);
927 void CL_ParseEffect2 (void)
930 int modelindex, startframe, framecount, framerate;
933 modelindex = MSG_ReadShort ();
934 startframe = MSG_ReadShort ();
935 framecount = MSG_ReadByte ();
936 framerate = MSG_ReadByte ();
938 CL_Effect(org, modelindex, startframe, framecount, framerate);
942 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
944 static qbyte cgamenetbuffer[65536];
947 =====================
948 CL_ParseServerMessage
949 =====================
951 void CL_ParseServerMessage (void)
954 int i, entitiesupdated;
956 char *cmdlogname[32], *temp;
957 int cmdindex, cmdcount = 0;
960 // if recording demos, copy the message out
962 if (cl_shownet.integer == 1)
963 Con_Printf ("%i ",net_message.cursize);
964 else if (cl_shownet.integer == 2)
965 Con_Printf ("------------------\n");
967 cl.onground = false; // unless the server says otherwise
973 entitiesupdated = false;
974 CL_EntityUpdateSetup();
979 Host_Error ("CL_ParseServerMessage: Bad server message");
981 cmd = MSG_ReadByte ();
985 SHOWNET("END OF MESSAGE");
986 break; // end of message
989 cmdindex = cmdcount & 31;
991 cmdlog[cmdindex] = cmd;
993 // if the high bit of the command byte is set, it is a fast update
996 // 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)
998 cmdlogname[cmdindex] = temp;
999 SHOWNET("fast update");
1000 if (cls.signon == SIGNONS - 1)
1001 { // first update is the final signon stage
1002 cls.signon = SIGNONS;
1005 CL_ParseUpdate (cmd&127);
1009 SHOWNET(svc_strings[cmd]);
1010 cmdlogname[cmdindex] = svc_strings[cmd];
1011 if (!cmdlogname[cmdindex])
1013 // 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)
1015 cmdlogname[cmdindex] = temp;
1023 char description[32*64], temp[64];
1025 strcpy(description, "packet dump: ");
1029 count = cmdcount - i;
1033 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1034 strcat(description, temp);
1039 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1040 Con_Printf("%s", description);
1041 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1049 // handle old protocols which do not have entity update ranges
1050 entitiesupdated = true;
1051 cl.mtime[1] = cl.mtime[0];
1052 cl.mtime[0] = MSG_ReadFloat ();
1055 case svc_clientdata:
1056 i = MSG_ReadShort ();
1057 CL_ParseClientdata (i);
1061 i = MSG_ReadLong ();
1062 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1063 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1064 Nehahrademcompatibility = false;
1066 Nehahrademcompatibility = true;
1067 if (cls.demoplayback && demo_nehahra.integer)
1068 Nehahrademcompatibility = true;
1070 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1074 case svc_disconnect:
1075 Host_EndGame ("Server disconnected\n");
1078 Con_Printf ("%s", MSG_ReadString ());
1081 case svc_centerprint:
1082 SCR_CenterPrint (MSG_ReadString ());
1086 Cbuf_AddText (MSG_ReadString ());
1093 case svc_serverinfo:
1094 CL_ParseServerInfo ();
1098 for (i=0 ; i<3 ; i++)
1099 cl.viewangles[i] = MSG_ReadAngle ();
1103 cl.viewentity = MSG_ReadShort ();
1106 case svc_lightstyle:
1107 i = MSG_ReadByte ();
1108 if (i >= MAX_LIGHTSTYLES)
1109 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1110 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1111 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1112 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1116 CL_ParseStartSoundPacket(false);
1120 CL_ParseStartSoundPacket(true);
1124 i = MSG_ReadShort();
1125 S_StopSound(i>>3, i&7);
1128 case svc_updatename:
1129 i = MSG_ReadByte ();
1130 if (i >= cl.maxclients)
1131 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1132 strcpy (cl.scores[i].name, MSG_ReadString ());
1135 case svc_updatefrags:
1136 i = MSG_ReadByte ();
1137 if (i >= cl.maxclients)
1138 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1139 cl.scores[i].frags = MSG_ReadShort ();
1142 case svc_updatecolors:
1143 i = MSG_ReadByte ();
1144 if (i >= cl.maxclients)
1145 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1146 cl.scores[i].colors = MSG_ReadByte ();
1150 CL_ParseParticleEffect ();
1161 case svc_spawnbaseline:
1162 i = MSG_ReadShort ();
1163 // must use CL_EntityNum() to force cl.num_entities up
1164 CL_ParseBaseline (CL_EntityNum(i), false);
1166 case svc_spawnbaseline2:
1167 i = MSG_ReadShort ();
1168 // must use CL_EntityNum() to force cl.num_entities up
1169 CL_ParseBaseline (CL_EntityNum(i), true);
1171 case svc_spawnstatic:
1172 CL_ParseStatic (false);
1174 case svc_spawnstatic2:
1175 CL_ParseStatic (true);
1177 case svc_temp_entity:
1182 cl.paused = MSG_ReadByte ();
1190 i = MSG_ReadByte ();
1191 if (i <= cls.signon)
1192 Host_Error ("Received signon %i when at %i", i, cls.signon);
1197 case svc_killedmonster:
1198 cl.stats[STAT_MONSTERS]++;
1201 case svc_foundsecret:
1202 cl.stats[STAT_SECRETS]++;
1205 case svc_updatestat:
1206 i = MSG_ReadByte ();
1207 if (i < 0 || i >= MAX_CL_STATS)
1208 Host_Error ("svc_updatestat: %i is invalid", i);
1209 cl.stats[i] = MSG_ReadLong ();
1212 case svc_spawnstaticsound:
1213 CL_ParseStaticSound (false);
1216 case svc_spawnstaticsound2:
1217 CL_ParseStaticSound (true);
1221 cl.cdtrack = MSG_ReadByte ();
1222 cl.looptrack = MSG_ReadByte ();
1223 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1224 CDAudio_Play ((qbyte)cls.forcetrack, true);
1226 CDAudio_Play ((qbyte)cl.cdtrack, true);
1229 case svc_intermission:
1230 cl.intermission = 1;
1231 cl.completed_time = cl.time;
1235 cl.intermission = 2;
1236 cl.completed_time = cl.time;
1237 SCR_CenterPrint (MSG_ReadString ());
1241 cl.intermission = 3;
1242 cl.completed_time = cl.time;
1243 SCR_CenterPrint (MSG_ReadString ());
1246 case svc_sellscreen:
1247 Cmd_ExecuteString ("help", src_command);
1250 SHOWLMP_decodehide();
1253 SHOWLMP_decodeshow();
1256 R_SetSkyBox(MSG_ReadString());
1261 length = (int) ((unsigned short) MSG_ReadShort());
1262 for (i = 0;i < length;i++)
1263 cgamenetbuffer[i] = MSG_ReadByte();
1265 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1269 if (cls.signon == SIGNONS - 1)
1270 { // first update is the final signon stage
1271 cls.signon = SIGNONS;
1274 CL_ReadEntityFrame();
1279 if (entitiesupdated)
1280 CL_EntityUpdateEnd();