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 qboolean dpprotocol; // LordHavoc: whether or not the current network stream is the enhanced DarkPlaces protocol
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_VERSION && i != 250)
365 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
368 Nehahrademcompatibility = false;
370 Nehahrademcompatibility = true;
371 if (cls.demoplayback && demo_nehahra.integer)
372 Nehahrademcompatibility = true;
373 dpprotocol = i == DPPROTOCOL_VERSION;
376 cl.maxclients = MSG_ReadByte ();
377 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
379 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
382 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
385 cl.gametype = MSG_ReadByte ();
387 // parse signon message
388 str = MSG_ReadString ();
389 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
391 // seperate the printfs so the server message can have a color
392 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
394 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");
395 Con_Printf ("%c%s\n", 2, str);
399 // first we go through and touch all of the precache data that still
400 // happens to be in the cache, so precaching something else doesn't
401 // needlessly purge it
404 Mem_CheckSentinelsGlobal();
408 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 Con_Printf ("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 Con_Printf ("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);
446 Mem_CheckSentinelsGlobal();
451 // now we try to load everything else until a cache allocation fails
454 Mem_CheckSentinelsGlobal();
456 for (i=1 ; i<nummodels ; i++)
458 // LordHavoc: i == 1 means the first model is the world model
459 cl.model_precache[i] = Mod_ForName (model_precache[i], false, true, i == 1);
461 if (cl.model_precache[i] == NULL)
463 Con_Printf("Model %s not found\n", model_precache[i]);
466 CL_KeepaliveMessage ();
469 Mem_CheckSentinelsGlobal();
471 S_BeginPrecaching ();
472 for (i=1 ; i<numsounds ; i++)
474 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
475 CL_KeepaliveMessage ();
480 cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
481 cl_entities[0].render.scale = 1;
482 cl_entities[0].render.alpha = 1;
486 Mem_CheckSentinelsGlobal();
488 noclip_anglehack = false; // noclip is turned off at start
491 void CL_ValidateState(entity_state_t *s)
498 if (s->modelindex >= MAX_MODELS)
499 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
501 // colormap is client index + 1
502 if (s->colormap > cl.maxclients)
503 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
505 model = cl.model_precache[s->modelindex];
506 Mod_CheckLoaded(model);
507 if (model && s->frame >= model->numframes)
509 Con_Printf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
512 if (model && s->skin > 0 && s->skin >= model->numskins)
514 Con_Printf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
523 Parse an entity update message from the server
524 If an entities model or origin changes from frame to frame, it must be
525 relinked. Other attributes can change without relinking.
528 byte entkill[MAX_EDICTS];
529 int bitprofile[32], bitprofilecount = 0;
530 void CL_ParseUpdate (int bits)
532 int i, num, deltadie;
536 if (cls.signon == SIGNONS - 1)
537 { // first update is the final signon stage
538 cls.signon = SIGNONS;
542 if (bits & U_MOREBITS)
543 bits |= (MSG_ReadByte()<<8);
544 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
546 bits |= MSG_ReadByte() << 16;
547 if (bits & U_EXTEND2)
548 bits |= MSG_ReadByte() << 24;
551 if (bits & U_LONGENTITY)
552 num = (unsigned) MSG_ReadShort ();
554 num = (unsigned) MSG_ReadByte ();
556 if (num >= MAX_EDICTS)
557 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
559 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
561 // mark as visible (no kill)
564 ent = CL_EntityNum (num);
566 for (i = 0;i < 32;i++)
574 new = ent->state_current;
576 deltadie = true; // was not present in previous frame, leave hidden until next full update
579 new = ent->state_baseline;
581 new.time = cl.mtime[0];
585 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
586 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
587 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
588 if (bits & U_SKIN) new.skin = MSG_ReadByte();
589 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
590 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
591 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
592 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
593 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
594 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
595 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
596 if (bits & U_STEP) new.flags |= RENDER_STEP;
597 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
598 if (bits & U_SCALE) new.scale = MSG_ReadByte();
599 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
600 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
601 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
603 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);}
605 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
606 if (bits & U_COLORMOD) MSG_ReadByte();
608 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
609 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
610 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
611 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
612 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
614 // LordHavoc: to allow playback of the Nehahra movie
615 if (Nehahrademcompatibility && (bits & U_EXTEND1))
617 // LordHavoc: evil format
618 int i = MSG_ReadFloat();
619 int j = MSG_ReadFloat() * 255.0f;
623 new.effects |= EF_FULLBRIGHT;
627 else if (j == 0 || j >= 255)
639 CL_ValidateState(&new);
641 if (new.flags & RENDER_STEP) // FIXME: rename this flag?
643 // make time identical for memcmp
644 new.time = ent->state_current.time;
645 if (memcmp(&new, &ent->state_current, sizeof(entity_state_t)))
648 ent->state_previous = ent->state_current;
649 ent->state_current = new;
650 // assume 10fps animation
651 ent->state_previous.time = cl.mtime[0];
652 ent->state_current.time = cl.mtime[0] + 0.1; //ent->state_previous.time + 0.1;
657 ent->state_previous = ent->state_current;
658 ent->state_current = new;
662 char *bitprofilenames[32] =
686 "obsolete U_COLORMOD",
698 void CL_BitProfile_f(void)
701 Con_Printf("bitprofile: %i updates\n");
703 for (i = 0;i < 32;i++)
704 // if (bitprofile[i])
705 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
707 for (i = 0;i < 32;i++)
712 void CL_EntityUpdateSetup(void)
714 memset(entkill, 1, MAX_EDICTS);
717 void CL_EntityUpdateEnd(void)
720 for (i = 1;i < MAX_EDICTS;i++)
722 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
730 void CL_ParseBaseline (entity_t *ent, int large)
734 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
735 ent->state_baseline.active = true;
738 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
739 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
743 ent->state_baseline.modelindex = MSG_ReadByte ();
744 ent->state_baseline.frame = MSG_ReadByte ();
746 ent->state_baseline.colormap = MSG_ReadByte();
747 ent->state_baseline.skin = MSG_ReadByte();
748 for (i = 0;i < 3;i++)
750 ent->state_baseline.origin[i] = MSG_ReadCoord ();
751 ent->state_baseline.angles[i] = MSG_ReadAngle ();
753 ent->state_baseline.alpha = 255;
754 ent->state_baseline.scale = 16;
755 ent->state_baseline.glowsize = 0;
756 ent->state_baseline.glowcolor = 254;
757 ent->state_previous = ent->state_current = ent->state_baseline;
759 CL_ValidateState(&ent->state_baseline);
767 Server information pertaining to this client only
770 void CL_ParseClientdata (int bits)
775 if (bits & SU_EXTEND1)
776 bits |= (MSG_ReadByte() << 16);
777 if (bits & SU_EXTEND2)
778 bits |= (MSG_ReadByte() << 24);
780 if (bits & SU_VIEWHEIGHT)
781 cl.viewheight = MSG_ReadChar ();
783 cl.viewheight = DEFAULT_VIEWHEIGHT;
785 if (bits & SU_IDEALPITCH)
786 cl.idealpitch = MSG_ReadChar ();
790 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
791 for (i=0 ; i<3 ; i++)
793 if (bits & (SU_PUNCH1<<i) )
796 cl.punchangle[i] = MSG_ReadPreciseAngle();
798 cl.punchangle[i] = MSG_ReadChar();
801 cl.punchangle[i] = 0;
802 if (bits & (SU_PUNCHVEC1<<i))
803 cl.punchvector[i] = MSG_ReadFloatCoord();
805 cl.punchvector[i] = 0;
806 if (bits & (SU_VELOCITY1<<i) )
807 cl.mvelocity[0][i] = MSG_ReadChar()*16;
809 cl.mvelocity[0][i] = 0;
815 for (j=0 ; j<32 ; j++)
816 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
817 cl.item_gettime[j] = cl.time;
821 cl.onground = (bits & SU_ONGROUND) != 0;
822 cl.inwater = (bits & SU_INWATER) != 0;
824 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
825 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
826 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
827 cl.stats[STAT_HEALTH] = MSG_ReadShort();
828 cl.stats[STAT_AMMO] = MSG_ReadByte();
830 cl.stats[STAT_SHELLS] = MSG_ReadByte();
831 cl.stats[STAT_NAILS] = MSG_ReadByte();
832 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
833 cl.stats[STAT_CELLS] = MSG_ReadByte();
837 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
838 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
840 cl.stats[STAT_ACTIVEWEAPON] = i;
844 =====================
846 =====================
848 void CL_ParseStatic (int large)
852 if (cl.num_statics >= MAX_STATIC_ENTITIES)
853 Host_Error ("Too many static entities");
854 ent = &cl_static_entities[cl.num_statics++];
855 CL_ParseBaseline (ent, large);
857 // copy it to the current state
858 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
859 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
860 ent->render.framelerp = 0;
861 // make torchs play out of sync
862 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
863 ent->render.colormap = -1; // no special coloring
864 ent->render.skinnum = ent->state_baseline.skin;
865 ent->render.effects = ent->state_baseline.effects;
866 ent->render.alpha = 1;
867 ent->render.scale = 1;
868 ent->render.alpha = 1;
870 VectorCopy (ent->state_baseline.origin, ent->render.origin);
871 VectorCopy (ent->state_baseline.angles, ent->render.angles);
879 void CL_ParseStaticSound (int large)
882 int sound_num, vol, atten;
886 sound_num = (unsigned short) MSG_ReadShort ();
888 sound_num = MSG_ReadByte ();
889 vol = MSG_ReadByte ();
890 atten = MSG_ReadByte ();
892 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
895 void CL_ParseEffect (void)
898 int modelindex, startframe, framecount, framerate;
901 modelindex = MSG_ReadByte ();
902 startframe = MSG_ReadByte ();
903 framecount = MSG_ReadByte ();
904 framerate = MSG_ReadByte ();
906 CL_Effect(org, modelindex, startframe, framecount, framerate);
909 void CL_ParseEffect2 (void)
912 int modelindex, startframe, framecount, framerate;
915 modelindex = MSG_ReadShort ();
916 startframe = MSG_ReadShort ();
917 framecount = MSG_ReadByte ();
918 framerate = MSG_ReadByte ();
920 CL_Effect(org, modelindex, startframe, framecount, framerate);
924 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
927 =====================
928 CL_ParseServerMessage
929 =====================
931 void CL_ParseServerMessage (void)
934 int i, entitiesupdated;
936 char *cmdlogname[32], *temp;
937 int cmdindex, cmdcount = 0;
940 // if recording demos, copy the message out
942 if (cl_shownet.integer == 1)
943 Con_Printf ("%i ",net_message.cursize);
944 else if (cl_shownet.integer == 2)
945 Con_Printf ("------------------\n");
947 cl.onground = false; // unless the server says otherwise
953 entitiesupdated = false;
954 CL_EntityUpdateSetup();
959 Host_Error ("CL_ParseServerMessage: Bad server message");
961 cmd = MSG_ReadByte ();
965 SHOWNET("END OF MESSAGE");
966 break; // end of message
969 cmdindex = cmdcount & 31;
971 cmdlog[cmdindex] = cmd;
973 // if the high bit of the command byte is set, it is a fast update
976 // 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)
978 cmdlogname[cmdindex] = temp;
979 SHOWNET("fast update");
980 CL_ParseUpdate (cmd&127);
984 SHOWNET(svc_strings[cmd]);
985 cmdlogname[cmdindex] = svc_strings[cmd];
986 if (!cmdlogname[cmdindex])
988 // 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)
990 cmdlogname[cmdindex] = temp;
998 char description[32*64], temp[64];
1000 strcpy(description, "packet dump: ");
1004 count = cmdcount - i;
1008 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1009 strcat(description, temp);
1014 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1015 Con_Printf("%s", description);
1016 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1021 // Con_Printf ("svc_nop\n");
1025 // handle old protocols which do not have entity update ranges
1026 entitiesupdated = true;
1027 cl.mtime[1] = cl.mtime[0];
1028 cl.mtime[0] = MSG_ReadFloat ();
1031 case svc_clientdata:
1032 i = MSG_ReadShort ();
1033 CL_ParseClientdata (i);
1037 i = MSG_ReadLong ();
1038 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
1039 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
1040 Nehahrademcompatibility = false;
1042 Nehahrademcompatibility = true;
1043 if (cls.demoplayback && demo_nehahra.integer)
1044 Nehahrademcompatibility = true;
1045 dpprotocol = i == DPPROTOCOL_VERSION;
1048 case svc_disconnect:
1049 Host_EndGame ("Server disconnected\n");
1052 Con_Printf ("%s", MSG_ReadString ());
1055 case svc_centerprint:
1056 SCR_CenterPrint (MSG_ReadString ());
1060 Cbuf_AddText (MSG_ReadString ());
1067 case svc_serverinfo:
1068 CL_ParseServerInfo ();
1069 // vid.recalc_refdef = true; // leave intermission full screen
1073 for (i=0 ; i<3 ; i++)
1074 cl.viewangles[i] = MSG_ReadAngle ();
1078 cl.viewentity = MSG_ReadShort ();
1081 case svc_lightstyle:
1082 i = MSG_ReadByte ();
1083 if (i >= MAX_LIGHTSTYLES)
1084 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1085 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1086 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1087 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1091 CL_ParseStartSoundPacket(false);
1095 CL_ParseStartSoundPacket(true);
1099 i = MSG_ReadShort();
1100 S_StopSound(i>>3, i&7);
1103 case svc_updatename:
1104 i = MSG_ReadByte ();
1105 if (i >= cl.maxclients)
1106 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1107 strcpy (cl.scores[i].name, MSG_ReadString ());
1110 case svc_updatefrags:
1111 i = MSG_ReadByte ();
1112 if (i >= cl.maxclients)
1113 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1114 cl.scores[i].frags = MSG_ReadShort ();
1117 case svc_updatecolors:
1118 i = MSG_ReadByte ();
1119 if (i >= cl.maxclients)
1120 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1121 cl.scores[i].colors = MSG_ReadByte ();
1125 CL_ParseParticleEffect ();
1136 case svc_spawnbaseline:
1137 i = MSG_ReadShort ();
1138 // must use CL_EntityNum() to force cl.num_entities up
1139 CL_ParseBaseline (CL_EntityNum(i), false);
1141 case svc_spawnbaseline2:
1142 i = MSG_ReadShort ();
1143 // must use CL_EntityNum() to force cl.num_entities up
1144 CL_ParseBaseline (CL_EntityNum(i), true);
1146 case svc_spawnstatic:
1147 CL_ParseStatic (false);
1149 case svc_spawnstatic2:
1150 CL_ParseStatic (true);
1152 case svc_temp_entity:
1157 cl.paused = MSG_ReadByte ();
1165 i = MSG_ReadByte ();
1166 if (i <= cls.signon)
1167 Host_Error ("Received signon %i when at %i", i, cls.signon);
1172 case svc_killedmonster:
1173 cl.stats[STAT_MONSTERS]++;
1176 case svc_foundsecret:
1177 cl.stats[STAT_SECRETS]++;
1180 case svc_updatestat:
1181 i = MSG_ReadByte ();
1182 if (i < 0 || i >= MAX_CL_STATS)
1183 Host_Error ("svc_updatestat: %i is invalid", i);
1184 cl.stats[i] = MSG_ReadLong ();
1187 case svc_spawnstaticsound:
1188 CL_ParseStaticSound (false);
1191 case svc_spawnstaticsound2:
1192 CL_ParseStaticSound (true);
1196 cl.cdtrack = MSG_ReadByte ();
1197 cl.looptrack = MSG_ReadByte ();
1198 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1199 CDAudio_Play ((byte)cls.forcetrack, true);
1201 CDAudio_Play ((byte)cl.cdtrack, true);
1204 case svc_intermission:
1205 cl.intermission = 1;
1206 cl.completed_time = cl.time;
1207 // vid.recalc_refdef = true; // go to full screen
1211 cl.intermission = 2;
1212 cl.completed_time = cl.time;
1213 // vid.recalc_refdef = true; // go to full screen
1214 SCR_CenterPrint (MSG_ReadString ());
1218 cl.intermission = 3;
1219 cl.completed_time = cl.time;
1220 // vid.recalc_refdef = true; // go to full screen
1221 SCR_CenterPrint (MSG_ReadString ());
1224 case svc_sellscreen:
1225 Cmd_ExecuteString ("help", src_command);
1228 SHOWLMP_decodehide();
1231 SHOWLMP_decodeshow();
1234 R_SetSkyBox(MSG_ReadString());
1239 if (entitiesupdated)
1240 CL_EntityUpdateEnd();