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);
893 void CL_ParseStaticSound (int large)
896 int sound_num, vol, atten;
900 sound_num = (unsigned short) MSG_ReadShort ();
902 sound_num = MSG_ReadByte ();
903 vol = MSG_ReadByte ();
904 atten = MSG_ReadByte ();
906 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
909 void CL_ParseEffect (void)
912 int modelindex, startframe, framecount, framerate;
915 modelindex = MSG_ReadByte ();
916 startframe = MSG_ReadByte ();
917 framecount = MSG_ReadByte ();
918 framerate = MSG_ReadByte ();
920 CL_Effect(org, modelindex, startframe, framecount, framerate);
923 void CL_ParseEffect2 (void)
926 int modelindex, startframe, framecount, framerate;
929 modelindex = MSG_ReadShort ();
930 startframe = MSG_ReadShort ();
931 framecount = MSG_ReadByte ();
932 framerate = MSG_ReadByte ();
934 CL_Effect(org, modelindex, startframe, framecount, framerate);
938 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
940 static qbyte cgamenetbuffer[65536];
943 =====================
944 CL_ParseServerMessage
945 =====================
947 void CL_ParseServerMessage (void)
950 int i, entitiesupdated;
952 char *cmdlogname[32], *temp;
953 int cmdindex, cmdcount = 0;
956 // if recording demos, copy the message out
958 if (cl_shownet.integer == 1)
959 Con_Printf ("%i ",net_message.cursize);
960 else if (cl_shownet.integer == 2)
961 Con_Printf ("------------------\n");
963 cl.onground = false; // unless the server says otherwise
969 entitiesupdated = false;
970 CL_EntityUpdateSetup();
975 Host_Error ("CL_ParseServerMessage: Bad server message");
977 cmd = MSG_ReadByte ();
981 SHOWNET("END OF MESSAGE");
982 break; // end of message
985 cmdindex = cmdcount & 31;
987 cmdlog[cmdindex] = cmd;
989 // if the high bit of the command byte is set, it is a fast update
992 // 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)
994 cmdlogname[cmdindex] = temp;
995 SHOWNET("fast update");
996 if (cls.signon == SIGNONS - 1)
997 { // first update is the final signon stage
998 cls.signon = SIGNONS;
1001 CL_ParseUpdate (cmd&127);
1005 SHOWNET(svc_strings[cmd]);
1006 cmdlogname[cmdindex] = svc_strings[cmd];
1007 if (!cmdlogname[cmdindex])
1009 // 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)
1011 cmdlogname[cmdindex] = temp;
1019 char description[32*64], temp[64];
1021 strcpy(description, "packet dump: ");
1025 count = cmdcount - i;
1029 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1030 strcat(description, temp);
1035 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1036 Con_Printf("%s", description);
1037 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1045 // handle old protocols which do not have entity update ranges
1046 entitiesupdated = true;
1047 cl.mtime[1] = cl.mtime[0];
1048 cl.mtime[0] = MSG_ReadFloat ();
1051 case svc_clientdata:
1052 i = MSG_ReadShort ();
1053 CL_ParseClientdata (i);
1057 i = MSG_ReadLong ();
1058 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1059 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1060 Nehahrademcompatibility = false;
1062 Nehahrademcompatibility = true;
1063 if (cls.demoplayback && demo_nehahra.integer)
1064 Nehahrademcompatibility = true;
1066 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1070 case svc_disconnect:
1071 Host_EndGame ("Server disconnected\n");
1074 Con_Printf ("%s", MSG_ReadString ());
1077 case svc_centerprint:
1078 SCR_CenterPrint (MSG_ReadString ());
1082 Cbuf_AddText (MSG_ReadString ());
1089 case svc_serverinfo:
1090 CL_ParseServerInfo ();
1094 for (i=0 ; i<3 ; i++)
1095 cl.viewangles[i] = MSG_ReadAngle ();
1099 cl.viewentity = MSG_ReadShort ();
1102 case svc_lightstyle:
1103 i = MSG_ReadByte ();
1104 if (i >= MAX_LIGHTSTYLES)
1105 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1106 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1107 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1108 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1112 CL_ParseStartSoundPacket(false);
1116 CL_ParseStartSoundPacket(true);
1120 i = MSG_ReadShort();
1121 S_StopSound(i>>3, i&7);
1124 case svc_updatename:
1125 i = MSG_ReadByte ();
1126 if (i >= cl.maxclients)
1127 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1128 strcpy (cl.scores[i].name, MSG_ReadString ());
1131 case svc_updatefrags:
1132 i = MSG_ReadByte ();
1133 if (i >= cl.maxclients)
1134 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1135 cl.scores[i].frags = MSG_ReadShort ();
1138 case svc_updatecolors:
1139 i = MSG_ReadByte ();
1140 if (i >= cl.maxclients)
1141 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1142 cl.scores[i].colors = MSG_ReadByte ();
1146 CL_ParseParticleEffect ();
1157 case svc_spawnbaseline:
1158 i = MSG_ReadShort ();
1159 // must use CL_EntityNum() to force cl.num_entities up
1160 CL_ParseBaseline (CL_EntityNum(i), false);
1162 case svc_spawnbaseline2:
1163 i = MSG_ReadShort ();
1164 // must use CL_EntityNum() to force cl.num_entities up
1165 CL_ParseBaseline (CL_EntityNum(i), true);
1167 case svc_spawnstatic:
1168 CL_ParseStatic (false);
1170 case svc_spawnstatic2:
1171 CL_ParseStatic (true);
1173 case svc_temp_entity:
1178 cl.paused = MSG_ReadByte ();
1186 i = MSG_ReadByte ();
1187 if (i <= cls.signon)
1188 Host_Error ("Received signon %i when at %i", i, cls.signon);
1193 case svc_killedmonster:
1194 cl.stats[STAT_MONSTERS]++;
1197 case svc_foundsecret:
1198 cl.stats[STAT_SECRETS]++;
1201 case svc_updatestat:
1202 i = MSG_ReadByte ();
1203 if (i < 0 || i >= MAX_CL_STATS)
1204 Host_Error ("svc_updatestat: %i is invalid", i);
1205 cl.stats[i] = MSG_ReadLong ();
1208 case svc_spawnstaticsound:
1209 CL_ParseStaticSound (false);
1212 case svc_spawnstaticsound2:
1213 CL_ParseStaticSound (true);
1217 cl.cdtrack = MSG_ReadByte ();
1218 cl.looptrack = MSG_ReadByte ();
1219 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1220 CDAudio_Play ((qbyte)cls.forcetrack, true);
1222 CDAudio_Play ((qbyte)cl.cdtrack, true);
1225 case svc_intermission:
1226 cl.intermission = 1;
1227 cl.completed_time = cl.time;
1231 cl.intermission = 2;
1232 cl.completed_time = cl.time;
1233 SCR_CenterPrint (MSG_ReadString ());
1237 cl.intermission = 3;
1238 cl.completed_time = cl.time;
1239 SCR_CenterPrint (MSG_ReadString ());
1242 case svc_sellscreen:
1243 Cmd_ExecuteString ("help", src_command);
1246 SHOWLMP_decodehide();
1249 SHOWLMP_decodeshow();
1252 R_SetSkyBox(MSG_ReadString());
1257 length = (int) ((unsigned short) MSG_ReadShort());
1258 for (i = 0;i < length;i++)
1259 cgamenetbuffer[i] = MSG_ReadByte();
1261 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1265 if (cls.signon == SIGNONS - 1)
1266 { // first update is the final signon stage
1267 cls.signon = SIGNONS;
1270 CL_ReadEntityFrame();
1275 if (entitiesupdated)
1276 CL_EntityUpdateEnd();