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
85 "svc_effect", // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
86 "svc_effect2", // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
89 //=============================================================================
91 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
93 void CL_Parse_Init(void)
95 // LordHavoc: added demo_nehahra cvar
96 Cvar_RegisterVariable (&demo_nehahra);
97 if (gamemode == GAME_NEHAHRA)
98 Cvar_SetValue("demo_nehahra", 1);
101 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
102 int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces
108 This error checks and tracks the total number of entities
111 entity_t *CL_EntityNum (int num)
114 if (num >= cl.num_entities)
116 if (num >= MAX_EDICTS)
117 Host_Error ("CL_EntityNum: %i is an invalid number",num);
118 cl.num_entities = num;
119 // while (cl.num_entities <= num)
121 // cl_entities[cl.num_entities].colormap = -1; // no special coloring
122 // cl.num_entities++;
126 if (num >= MAX_EDICTS)
127 Host_Error ("CL_EntityNum: %i is an invalid number",num);
129 return &cl_entities[num];
135 CL_ParseStartSoundPacket
138 void CL_ParseStartSoundPacket(int largesoundindex)
148 field_mask = MSG_ReadByte();
150 if (field_mask & SND_VOLUME)
151 volume = MSG_ReadByte ();
153 volume = DEFAULT_SOUND_PACKET_VOLUME;
155 if (field_mask & SND_ATTENUATION)
156 attenuation = MSG_ReadByte () / 64.0;
158 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
160 channel = MSG_ReadShort ();
162 sound_num = (unsigned short) MSG_ReadShort ();
164 sound_num = MSG_ReadByte ();
166 if (sound_num >= MAX_SOUNDS)
167 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
172 if (ent > MAX_EDICTS)
173 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
175 for (i=0 ; i<3 ; i++)
176 pos[i] = MSG_ReadCoord ();
178 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
185 When the client is taking a long time to load stuff, send keepalive messages
186 so the server doesn't disconnect.
189 void CL_KeepaliveMessage (void)
192 static float lastmsg;
198 return; // no need if server is local
199 if (cls.demoplayback)
202 // read messages from server, should just be nops
204 memcpy (olddata, net_message.data, net_message.cursize);
208 ret = CL_GetMessage ();
212 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
214 break; // nothing waiting
216 Host_Error ("CL_KeepaliveMessage: received a message");
219 if (MSG_ReadByte() != svc_nop)
220 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
226 memcpy (net_message.data, olddata, net_message.cursize);
229 time = Sys_DoubleTime ();
230 if (time - lastmsg < 5)
235 Con_Printf ("--> client to server keepalive\n");
237 MSG_WriteByte (&cls.message, clc_nop);
238 NET_SendMessage (cls.netcon, &cls.message);
239 SZ_Clear (&cls.message);
242 void CL_ParseEntityLump(char *entdata)
245 char key[128], value[4096];
246 FOG_clear(); // LordHavoc: no fog until set
247 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
251 data = COM_Parse(data);
254 if (com_token[0] != '{')
258 data = COM_Parse(data);
261 if (com_token[0] == '}')
262 break; // end of worldspawn
263 if (com_token[0] == '_')
264 strcpy(key, com_token + 1);
266 strcpy(key, com_token);
267 while (key[strlen(key)-1] == ' ') // remove trailing spaces
268 key[strlen(key)-1] = 0;
269 data = COM_Parse(data);
272 strcpy(value, com_token);
273 if (!strcmp("sky", key))
275 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
277 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
279 else if (!strcmp("fog", key))
280 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
281 else if (!strcmp("fog_density", key))
282 fog_density = atof(value);
283 else if (!strcmp("fog_red", key))
284 fog_red = atof(value);
285 else if (!strcmp("fog_green", key))
286 fog_green = atof(value);
287 else if (!strcmp("fog_blue", key))
288 fog_blue = atof(value);
293 =====================
296 An svc_signonnum has been received, perform a client side setup
297 =====================
299 static void CL_SignonReply (void)
303 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
308 MSG_WriteByte (&cls.message, clc_stringcmd);
309 MSG_WriteString (&cls.message, "prespawn");
313 MSG_WriteByte (&cls.message, clc_stringcmd);
314 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
316 MSG_WriteByte (&cls.message, clc_stringcmd);
317 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
319 if (cl_pmodel.integer)
321 MSG_WriteByte (&cls.message, clc_stringcmd);
322 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
325 MSG_WriteByte (&cls.message, clc_stringcmd);
326 sprintf (str, "spawn %s", cls.spawnparms);
327 MSG_WriteString (&cls.message, str);
331 MSG_WriteByte (&cls.message, clc_stringcmd);
332 MSG_WriteString (&cls.message, "begin");
336 // SCR_EndLoadingPlaque (); // allow normal screen updates
347 void CL_ParseServerInfo (void)
351 int nummodels, numsounds;
352 char model_precache[MAX_MODELS][MAX_QPATH];
353 char sound_precache[MAX_SOUNDS][MAX_QPATH];
355 Con_DPrintf ("Serverinfo packet received.\n");
357 // wipe the client_state_t struct
361 // parse protocol version number
363 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != 250)
365 Con_Printf ("Server is protocol %i, not %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, PROTOCOL_VERSION);
368 Nehahrademcompatibility = false;
370 Nehahrademcompatibility = true;
371 if (cls.demoplayback && demo_nehahra.integer)
372 Nehahrademcompatibility = true;
374 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2)
378 cl.maxclients = MSG_ReadByte ();
379 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
381 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
384 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
387 cl.gametype = MSG_ReadByte ();
389 // parse signon message
390 str = MSG_ReadString ();
391 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
393 // seperate the printfs so the server message can have a color
394 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
396 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");
397 Con_Printf ("%c%s\n", 2, str);
401 // first we go through and touch all of the precache data that still
402 // happens to be in the cache, so precaching something else doesn't
403 // needlessly purge it
406 Mem_CheckSentinelsGlobal();
411 memset (cl.model_precache, 0, sizeof(cl.model_precache));
412 for (nummodels=1 ; ; nummodels++)
414 str = MSG_ReadString ();
417 if (nummodels==MAX_MODELS)
419 Host_Error ("Server sent too many model precaches\n");
422 if (strlen(str) >= MAX_QPATH)
423 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
424 strcpy (model_precache[nummodels], str);
425 Mod_TouchModel (str);
429 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
430 for (numsounds=1 ; ; numsounds++)
432 str = MSG_ReadString ();
435 if (numsounds==MAX_SOUNDS)
437 Host_Error ("Server sent too many sound precaches\n");
440 if (strlen(str) >= MAX_QPATH)
441 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
442 strcpy (sound_precache[numsounds], str);
449 // now we try to load everything else until a cache allocation fails
452 Mem_CheckSentinelsGlobal();
454 for (i=1 ; i<nummodels ; i++)
456 // LordHavoc: i == 1 means the first model is the world model
457 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
459 if (cl.model_precache[i] == NULL)
461 Host_Error("Model %s not found\n", model_precache[i]);
464 CL_KeepaliveMessage ();
467 Mem_CheckSentinelsGlobal();
469 S_BeginPrecaching ();
470 for (i=1 ; i<numsounds ; i++)
472 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
473 CL_KeepaliveMessage ();
478 cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
479 cl_entities[0].render.scale = 1;
480 cl_entities[0].render.alpha = 1;
484 Mem_CheckSentinelsGlobal();
488 Mem_CheckSentinelsGlobal();
490 noclip_anglehack = false; // noclip is turned off at start
493 void CL_ValidateState(entity_state_t *s)
500 if (s->modelindex >= MAX_MODELS)
501 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
503 // colormap is client index + 1
504 if (s->colormap > cl.maxclients)
505 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
507 model = cl.model_precache[s->modelindex];
508 Mod_CheckLoaded(model);
509 if (model && s->frame >= model->numframes)
511 Con_Printf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
514 if (model && s->skin > 0 && s->skin >= model->numskins)
516 Con_Printf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
525 Parse an entity update message from the server
526 If an entities model or origin changes from frame to frame, it must be
527 relinked. Other attributes can change without relinking.
530 byte entkill[MAX_EDICTS];
531 int bitprofile[32], bitprofilecount = 0;
532 void CL_ParseUpdate (int bits)
534 int i, num, deltadie;
538 if (bits & U_MOREBITS)
539 bits |= (MSG_ReadByte()<<8);
540 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
542 bits |= MSG_ReadByte() << 16;
543 if (bits & U_EXTEND2)
544 bits |= MSG_ReadByte() << 24;
547 if (bits & U_LONGENTITY)
548 num = (unsigned) MSG_ReadShort ();
550 num = (unsigned) MSG_ReadByte ();
552 if (num >= MAX_EDICTS)
553 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
555 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
557 // mark as visible (no kill)
560 ent = CL_EntityNum (num);
562 for (i = 0;i < 32;i++)
570 new = ent->state_current;
572 deltadie = true; // was not present in previous frame, leave hidden until next full update
575 new = ent->state_baseline;
577 new.time = cl.mtime[0];
581 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
582 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
583 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
584 if (bits & U_SKIN) new.skin = MSG_ReadByte();
585 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
586 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
587 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
588 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
589 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
590 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
591 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
592 if (bits & U_STEP) new.flags |= RENDER_STEP;
593 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
594 if (bits & U_SCALE) new.scale = MSG_ReadByte();
595 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
596 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
597 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
599 if (bits & U_COLORMOD) {int i = MSG_ReadByte();float r = (((int) i >> 5) & 7) * 1.0 / 7, g = (((int) i >> 2) & 7) * 1.0 / 7, b = ((int) i & 3) * 1.0 / 3;Con_Printf("warning: U_COLORMOD %i (%1.2f %1.2f %1.2f) ignored\n", i, r, g, b);}
601 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
602 if (bits & U_COLORMOD) MSG_ReadByte();
604 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
605 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
606 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
607 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
608 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
610 // LordHavoc: to allow playback of the Nehahra movie
611 if (Nehahrademcompatibility && (bits & U_EXTEND1))
613 // LordHavoc: evil format
614 int i = MSG_ReadFloat();
615 int j = MSG_ReadFloat() * 255.0f;
619 new.effects |= EF_FULLBRIGHT;
623 else if (j == 0 || j >= 255)
635 CL_ValidateState(&new);
637 if (new.flags & RENDER_STEP) // FIXME: rename this flag?
639 // make time identical for memcmp
640 new.time = ent->state_current.time;
641 if (memcmp(&new, &ent->state_current, sizeof(entity_state_t)))
643 // set it back to what it should be
644 new.time = cl.mtime[0] + 0.1;
646 ent->state_previous = ent->state_current;
647 ent->state_current = new;
648 // assume 10fps animation
649 //ent->state_previous.time = cl.mtime[0] - 0.1;
654 ent->state_previous = ent->state_current;
655 ent->state_current = new;
659 void CL_ReadEntityFrame(void)
663 entity_frame_t entityframe;
665 EntityFrame_Read(&cl.entitydatabase);
666 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
667 for (i = 0;i < entityframe.numentities;i++)
669 s = &entityframe.entitydata[i];
670 entkill[s->number] = 0;
671 ent = &cl_entities[s->number];
672 memcpy(&ent->state_previous, &ent->state_current, sizeof(*s));
673 memcpy(&ent->state_current, s, sizeof(*s));
674 ent->state_current.time = cl.mtime[0];
676 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
677 VectorCopy(entityframe.eye, cl.viewentoriginnew);
680 char *bitprofilenames[32] =
704 "obsolete U_COLORMOD",
716 void CL_BitProfile_f(void)
719 Con_Printf("bitprofile: %i updates\n");
721 for (i = 0;i < 32;i++)
722 // if (bitprofile[i])
723 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
725 for (i = 0;i < 32;i++)
730 void CL_EntityUpdateSetup(void)
732 memset(entkill, 1, MAX_EDICTS);
735 void CL_EntityUpdateEnd(void)
738 for (i = 1;i < MAX_EDICTS;i++)
740 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
748 void CL_ParseBaseline (entity_t *ent, int large)
752 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
753 ent->state_baseline.active = true;
756 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
757 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
761 ent->state_baseline.modelindex = MSG_ReadByte ();
762 ent->state_baseline.frame = MSG_ReadByte ();
764 ent->state_baseline.colormap = MSG_ReadByte();
765 ent->state_baseline.skin = MSG_ReadByte();
766 for (i = 0;i < 3;i++)
768 ent->state_baseline.origin[i] = MSG_ReadCoord ();
769 ent->state_baseline.angles[i] = MSG_ReadAngle ();
771 ent->state_baseline.alpha = 255;
772 ent->state_baseline.scale = 16;
773 ent->state_baseline.glowsize = 0;
774 ent->state_baseline.glowcolor = 254;
775 ent->state_previous = ent->state_current = ent->state_baseline;
777 CL_ValidateState(&ent->state_baseline);
785 Server information pertaining to this client only
788 void CL_ParseClientdata (int bits)
793 if (bits & SU_EXTEND1)
794 bits |= (MSG_ReadByte() << 16);
795 if (bits & SU_EXTEND2)
796 bits |= (MSG_ReadByte() << 24);
798 if (bits & SU_VIEWHEIGHT)
799 cl.viewheight = MSG_ReadChar ();
801 cl.viewheight = DEFAULT_VIEWHEIGHT;
803 if (bits & SU_IDEALPITCH)
804 cl.idealpitch = MSG_ReadChar ();
808 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
809 for (i=0 ; i<3 ; i++)
811 if (bits & (SU_PUNCH1<<i) )
814 cl.punchangle[i] = MSG_ReadPreciseAngle();
816 cl.punchangle[i] = MSG_ReadChar();
819 cl.punchangle[i] = 0;
820 if (bits & (SU_PUNCHVEC1<<i))
821 cl.punchvector[i] = MSG_ReadCoord();
823 cl.punchvector[i] = 0;
824 if (bits & (SU_VELOCITY1<<i) )
825 cl.mvelocity[0][i] = MSG_ReadChar()*16;
827 cl.mvelocity[0][i] = 0;
833 for (j=0 ; j<32 ; j++)
834 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
835 cl.item_gettime[j] = cl.time;
839 cl.onground = (bits & SU_ONGROUND) != 0;
840 cl.inwater = (bits & SU_INWATER) != 0;
842 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
843 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
844 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
845 cl.stats[STAT_HEALTH] = MSG_ReadShort();
846 cl.stats[STAT_AMMO] = MSG_ReadByte();
848 cl.stats[STAT_SHELLS] = MSG_ReadByte();
849 cl.stats[STAT_NAILS] = MSG_ReadByte();
850 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
851 cl.stats[STAT_CELLS] = MSG_ReadByte();
855 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
856 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
858 cl.stats[STAT_ACTIVEWEAPON] = i;
862 =====================
864 =====================
866 void CL_ParseStatic (int large)
870 if (cl.num_statics >= MAX_STATIC_ENTITIES)
871 Host_Error ("Too many static entities");
872 ent = &cl_static_entities[cl.num_statics++];
873 CL_ParseBaseline (ent, large);
875 // copy it to the current state
876 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
877 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
878 ent->render.framelerp = 0;
879 // make torchs play out of sync
880 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
881 ent->render.colormap = -1; // no special coloring
882 ent->render.skinnum = ent->state_baseline.skin;
883 ent->render.effects = ent->state_baseline.effects;
884 ent->render.alpha = 1;
885 ent->render.scale = 1;
886 ent->render.alpha = 1;
888 VectorCopy (ent->state_baseline.origin, ent->render.origin);
889 VectorCopy (ent->state_baseline.angles, ent->render.angles);
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 byte 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");
1046 // Con_Printf ("svc_nop\n");
1050 // handle old protocols which do not have entity update ranges
1051 entitiesupdated = true;
1052 cl.mtime[1] = cl.mtime[0];
1053 cl.mtime[0] = MSG_ReadFloat ();
1056 case svc_clientdata:
1057 i = MSG_ReadShort ();
1058 CL_ParseClientdata (i);
1062 i = MSG_ReadLong ();
1063 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != 250)
1064 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, PROTOCOL_VERSION);
1065 Nehahrademcompatibility = false;
1067 Nehahrademcompatibility = true;
1068 if (cls.demoplayback && demo_nehahra.integer)
1069 Nehahrademcompatibility = true;
1071 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2)
1075 case svc_disconnect:
1076 Host_EndGame ("Server disconnected\n");
1079 Con_Printf ("%s", MSG_ReadString ());
1082 case svc_centerprint:
1083 SCR_CenterPrint (MSG_ReadString ());
1087 Cbuf_AddText (MSG_ReadString ());
1094 case svc_serverinfo:
1095 CL_ParseServerInfo ();
1096 // vid.recalc_refdef = true; // leave intermission full screen
1100 for (i=0 ; i<3 ; i++)
1101 cl.viewangles[i] = MSG_ReadAngle ();
1105 cl.viewentity = MSG_ReadShort ();
1108 case svc_lightstyle:
1109 i = MSG_ReadByte ();
1110 if (i >= MAX_LIGHTSTYLES)
1111 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1112 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1113 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1114 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1118 CL_ParseStartSoundPacket(false);
1122 CL_ParseStartSoundPacket(true);
1126 i = MSG_ReadShort();
1127 S_StopSound(i>>3, i&7);
1130 case svc_updatename:
1131 i = MSG_ReadByte ();
1132 if (i >= cl.maxclients)
1133 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1134 strcpy (cl.scores[i].name, MSG_ReadString ());
1137 case svc_updatefrags:
1138 i = MSG_ReadByte ();
1139 if (i >= cl.maxclients)
1140 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1141 cl.scores[i].frags = MSG_ReadShort ();
1144 case svc_updatecolors:
1145 i = MSG_ReadByte ();
1146 if (i >= cl.maxclients)
1147 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1148 cl.scores[i].colors = MSG_ReadByte ();
1152 CL_ParseParticleEffect ();
1163 case svc_spawnbaseline:
1164 i = MSG_ReadShort ();
1165 // must use CL_EntityNum() to force cl.num_entities up
1166 CL_ParseBaseline (CL_EntityNum(i), false);
1168 case svc_spawnbaseline2:
1169 i = MSG_ReadShort ();
1170 // must use CL_EntityNum() to force cl.num_entities up
1171 CL_ParseBaseline (CL_EntityNum(i), true);
1173 case svc_spawnstatic:
1174 CL_ParseStatic (false);
1176 case svc_spawnstatic2:
1177 CL_ParseStatic (true);
1179 case svc_temp_entity:
1184 cl.paused = MSG_ReadByte ();
1192 i = MSG_ReadByte ();
1193 if (i <= cls.signon)
1194 Host_Error ("Received signon %i when at %i", i, cls.signon);
1199 case svc_killedmonster:
1200 cl.stats[STAT_MONSTERS]++;
1203 case svc_foundsecret:
1204 cl.stats[STAT_SECRETS]++;
1207 case svc_updatestat:
1208 i = MSG_ReadByte ();
1209 if (i < 0 || i >= MAX_CL_STATS)
1210 Host_Error ("svc_updatestat: %i is invalid", i);
1211 cl.stats[i] = MSG_ReadLong ();
1214 case svc_spawnstaticsound:
1215 CL_ParseStaticSound (false);
1218 case svc_spawnstaticsound2:
1219 CL_ParseStaticSound (true);
1223 cl.cdtrack = MSG_ReadByte ();
1224 cl.looptrack = MSG_ReadByte ();
1225 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1226 CDAudio_Play ((byte)cls.forcetrack, true);
1228 CDAudio_Play ((byte)cl.cdtrack, true);
1231 case svc_intermission:
1232 cl.intermission = 1;
1233 cl.completed_time = cl.time;
1234 // vid.recalc_refdef = true; // go to full screen
1238 cl.intermission = 2;
1239 cl.completed_time = cl.time;
1240 // vid.recalc_refdef = true; // go to full screen
1241 SCR_CenterPrint (MSG_ReadString ());
1245 cl.intermission = 3;
1246 cl.completed_time = cl.time;
1247 // vid.recalc_refdef = true; // go to full screen
1248 SCR_CenterPrint (MSG_ReadString ());
1251 case svc_sellscreen:
1252 Cmd_ExecuteString ("help", src_command);
1255 SHOWLMP_decodehide();
1258 SHOWLMP_decodeshow();
1261 R_SetSkyBox(MSG_ReadString());
1266 length = (int) ((unsigned short) MSG_ReadShort());
1268 if (cgamenetbuffersize < length)
1270 cgamenetbuffersize = length;
1272 Mem_Free(cgamenetbuffer);
1273 cgamenetbuffer = Mem_Alloc(cgamenetbuffersize);
1276 for (i = 0;i < length;i++)
1277 cgamenetbuffer[i] = MSG_ReadByte();
1279 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1283 if (cls.signon == SIGNONS - 1)
1284 { // first update is the final signon stage
1285 cls.signon = SIGNONS;
1288 CL_ReadEntityFrame();
1293 if (entitiesupdated)
1294 CL_EntityUpdateEnd();