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();
409 memset (cl.model_precache, 0, sizeof(cl.model_precache));
410 for (nummodels=1 ; ; nummodels++)
412 str = MSG_ReadString ();
415 if (nummodels==MAX_MODELS)
417 Host_Error ("Server sent too many model precaches\n");
420 if (strlen(str) >= MAX_QPATH)
421 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
422 strcpy (model_precache[nummodels], str);
423 Mod_TouchModel (str);
427 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
428 for (numsounds=1 ; ; numsounds++)
430 str = MSG_ReadString ();
433 if (numsounds==MAX_SOUNDS)
435 Host_Error ("Server sent too many sound precaches\n");
438 if (strlen(str) >= MAX_QPATH)
439 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
440 strcpy (sound_precache[numsounds], str);
447 // now we try to load everything else until a cache allocation fails
450 Mem_CheckSentinelsGlobal();
452 for (i=1 ; i<nummodels ; i++)
454 // LordHavoc: i == 1 means the first model is the world model
455 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
457 if (cl.model_precache[i] == NULL)
459 Host_Error("Model %s not found\n", model_precache[i]);
462 CL_KeepaliveMessage ();
465 Mem_CheckSentinelsGlobal();
467 S_BeginPrecaching ();
468 for (i=1 ; i<numsounds ; i++)
470 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
471 CL_KeepaliveMessage ();
476 cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
477 cl_entities[0].render.scale = 1;
478 cl_entities[0].render.alpha = 1;
482 Mem_CheckSentinelsGlobal();
484 noclip_anglehack = false; // noclip is turned off at start
487 void CL_ValidateState(entity_state_t *s)
494 if (s->modelindex >= MAX_MODELS)
495 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
497 // colormap is client index + 1
498 if (s->colormap > cl.maxclients)
499 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
501 model = cl.model_precache[s->modelindex];
502 Mod_CheckLoaded(model);
503 if (model && s->frame >= model->numframes)
505 Con_Printf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
508 if (model && s->skin > 0 && s->skin >= model->numskins)
510 Con_Printf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
519 Parse an entity update message from the server
520 If an entities model or origin changes from frame to frame, it must be
521 relinked. Other attributes can change without relinking.
524 byte entkill[MAX_EDICTS];
525 int bitprofile[32], bitprofilecount = 0;
526 void CL_ParseUpdate (int bits)
528 int i, num, deltadie;
532 if (cls.signon == SIGNONS - 1)
533 { // first update is the final signon stage
534 cls.signon = SIGNONS;
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)))
644 ent->state_previous = ent->state_current;
645 ent->state_current = new;
646 // assume 10fps animation
647 ent->state_previous.time = cl.mtime[0];
648 ent->state_current.time = cl.mtime[0] + 0.1; //ent->state_previous.time + 0.1;
653 ent->state_previous = ent->state_current;
654 ent->state_current = new;
658 char *bitprofilenames[32] =
682 "obsolete U_COLORMOD",
694 void CL_BitProfile_f(void)
697 Con_Printf("bitprofile: %i updates\n");
699 for (i = 0;i < 32;i++)
700 // if (bitprofile[i])
701 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
703 for (i = 0;i < 32;i++)
708 void CL_EntityUpdateSetup(void)
710 memset(entkill, 1, MAX_EDICTS);
713 void CL_EntityUpdateEnd(void)
716 for (i = 1;i < MAX_EDICTS;i++)
718 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
726 void CL_ParseBaseline (entity_t *ent, int large)
730 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
731 ent->state_baseline.active = true;
734 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
735 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
739 ent->state_baseline.modelindex = MSG_ReadByte ();
740 ent->state_baseline.frame = MSG_ReadByte ();
742 ent->state_baseline.colormap = MSG_ReadByte();
743 ent->state_baseline.skin = MSG_ReadByte();
744 for (i = 0;i < 3;i++)
746 ent->state_baseline.origin[i] = MSG_ReadCoord ();
747 ent->state_baseline.angles[i] = MSG_ReadAngle ();
749 ent->state_baseline.alpha = 255;
750 ent->state_baseline.scale = 16;
751 ent->state_baseline.glowsize = 0;
752 ent->state_baseline.glowcolor = 254;
753 ent->state_previous = ent->state_current = ent->state_baseline;
755 CL_ValidateState(&ent->state_baseline);
763 Server information pertaining to this client only
766 void CL_ParseClientdata (int bits)
771 if (bits & SU_EXTEND1)
772 bits |= (MSG_ReadByte() << 16);
773 if (bits & SU_EXTEND2)
774 bits |= (MSG_ReadByte() << 24);
776 if (bits & SU_VIEWHEIGHT)
777 cl.viewheight = MSG_ReadChar ();
779 cl.viewheight = DEFAULT_VIEWHEIGHT;
781 if (bits & SU_IDEALPITCH)
782 cl.idealpitch = MSG_ReadChar ();
786 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
787 for (i=0 ; i<3 ; i++)
789 if (bits & (SU_PUNCH1<<i) )
792 cl.punchangle[i] = MSG_ReadPreciseAngle();
794 cl.punchangle[i] = MSG_ReadChar();
797 cl.punchangle[i] = 0;
798 if (bits & (SU_PUNCHVEC1<<i))
799 cl.punchvector[i] = MSG_ReadFloatCoord();
801 cl.punchvector[i] = 0;
802 if (bits & (SU_VELOCITY1<<i) )
803 cl.mvelocity[0][i] = MSG_ReadChar()*16;
805 cl.mvelocity[0][i] = 0;
811 for (j=0 ; j<32 ; j++)
812 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
813 cl.item_gettime[j] = cl.time;
817 cl.onground = (bits & SU_ONGROUND) != 0;
818 cl.inwater = (bits & SU_INWATER) != 0;
820 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
821 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
822 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
823 cl.stats[STAT_HEALTH] = MSG_ReadShort();
824 cl.stats[STAT_AMMO] = MSG_ReadByte();
826 cl.stats[STAT_SHELLS] = MSG_ReadByte();
827 cl.stats[STAT_NAILS] = MSG_ReadByte();
828 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
829 cl.stats[STAT_CELLS] = MSG_ReadByte();
833 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
834 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
836 cl.stats[STAT_ACTIVEWEAPON] = i;
840 =====================
842 =====================
844 void CL_ParseStatic (int large)
848 if (cl.num_statics >= MAX_STATIC_ENTITIES)
849 Host_Error ("Too many static entities");
850 ent = &cl_static_entities[cl.num_statics++];
851 CL_ParseBaseline (ent, large);
853 // copy it to the current state
854 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
855 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
856 ent->render.framelerp = 0;
857 // make torchs play out of sync
858 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
859 ent->render.colormap = -1; // no special coloring
860 ent->render.skinnum = ent->state_baseline.skin;
861 ent->render.effects = ent->state_baseline.effects;
862 ent->render.alpha = 1;
863 ent->render.scale = 1;
864 ent->render.alpha = 1;
866 VectorCopy (ent->state_baseline.origin, ent->render.origin);
867 VectorCopy (ent->state_baseline.angles, ent->render.angles);
875 void CL_ParseStaticSound (int large)
878 int sound_num, vol, atten;
882 sound_num = (unsigned short) MSG_ReadShort ();
884 sound_num = MSG_ReadByte ();
885 vol = MSG_ReadByte ();
886 atten = MSG_ReadByte ();
888 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
891 void CL_ParseEffect (void)
894 int modelindex, startframe, framecount, framerate;
897 modelindex = MSG_ReadByte ();
898 startframe = MSG_ReadByte ();
899 framecount = MSG_ReadByte ();
900 framerate = MSG_ReadByte ();
902 CL_Effect(org, modelindex, startframe, framecount, framerate);
905 void CL_ParseEffect2 (void)
908 int modelindex, startframe, framecount, framerate;
911 modelindex = MSG_ReadShort ();
912 startframe = MSG_ReadShort ();
913 framecount = MSG_ReadByte ();
914 framerate = MSG_ReadByte ();
916 CL_Effect(org, modelindex, startframe, framecount, framerate);
920 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
923 =====================
924 CL_ParseServerMessage
925 =====================
927 void CL_ParseServerMessage (void)
930 int i, entitiesupdated;
932 char *cmdlogname[32], *temp;
933 int cmdindex, cmdcount = 0;
936 // if recording demos, copy the message out
938 if (cl_shownet.integer == 1)
939 Con_Printf ("%i ",net_message.cursize);
940 else if (cl_shownet.integer == 2)
941 Con_Printf ("------------------\n");
943 cl.onground = false; // unless the server says otherwise
949 entitiesupdated = false;
950 CL_EntityUpdateSetup();
955 Host_Error ("CL_ParseServerMessage: Bad server message");
957 cmd = MSG_ReadByte ();
961 SHOWNET("END OF MESSAGE");
962 break; // end of message
965 cmdindex = cmdcount & 31;
967 cmdlog[cmdindex] = cmd;
969 // if the high bit of the command byte is set, it is a fast update
972 // 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)
974 cmdlogname[cmdindex] = temp;
975 SHOWNET("fast update");
976 CL_ParseUpdate (cmd&127);
980 SHOWNET(svc_strings[cmd]);
981 cmdlogname[cmdindex] = svc_strings[cmd];
982 if (!cmdlogname[cmdindex])
984 // 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)
986 cmdlogname[cmdindex] = temp;
994 char description[32*64], temp[64];
996 strcpy(description, "packet dump: ");
1000 count = cmdcount - i;
1004 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1005 strcat(description, temp);
1010 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1011 Con_Printf("%s", description);
1012 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1017 // Con_Printf ("svc_nop\n");
1021 // handle old protocols which do not have entity update ranges
1022 entitiesupdated = true;
1023 cl.mtime[1] = cl.mtime[0];
1024 cl.mtime[0] = MSG_ReadFloat ();
1027 case svc_clientdata:
1028 i = MSG_ReadShort ();
1029 CL_ParseClientdata (i);
1033 i = MSG_ReadLong ();
1034 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
1035 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
1036 Nehahrademcompatibility = false;
1038 Nehahrademcompatibility = true;
1039 if (cls.demoplayback && demo_nehahra.integer)
1040 Nehahrademcompatibility = true;
1041 dpprotocol = i == DPPROTOCOL_VERSION;
1044 case svc_disconnect:
1045 Host_EndGame ("Server disconnected\n");
1048 Con_Printf ("%s", MSG_ReadString ());
1051 case svc_centerprint:
1052 SCR_CenterPrint (MSG_ReadString ());
1056 Cbuf_AddText (MSG_ReadString ());
1063 case svc_serverinfo:
1064 CL_ParseServerInfo ();
1065 // vid.recalc_refdef = true; // leave intermission full screen
1069 for (i=0 ; i<3 ; i++)
1070 cl.viewangles[i] = MSG_ReadAngle ();
1074 cl.viewentity = MSG_ReadShort ();
1077 case svc_lightstyle:
1078 i = MSG_ReadByte ();
1079 if (i >= MAX_LIGHTSTYLES)
1080 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1081 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1082 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1083 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1087 CL_ParseStartSoundPacket(false);
1091 CL_ParseStartSoundPacket(true);
1095 i = MSG_ReadShort();
1096 S_StopSound(i>>3, i&7);
1099 case svc_updatename:
1100 i = MSG_ReadByte ();
1101 if (i >= cl.maxclients)
1102 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1103 strcpy (cl.scores[i].name, MSG_ReadString ());
1106 case svc_updatefrags:
1107 i = MSG_ReadByte ();
1108 if (i >= cl.maxclients)
1109 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1110 cl.scores[i].frags = MSG_ReadShort ();
1113 case svc_updatecolors:
1114 i = MSG_ReadByte ();
1115 if (i >= cl.maxclients)
1116 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1117 cl.scores[i].colors = MSG_ReadByte ();
1121 CL_ParseParticleEffect ();
1132 case svc_spawnbaseline:
1133 i = MSG_ReadShort ();
1134 // must use CL_EntityNum() to force cl.num_entities up
1135 CL_ParseBaseline (CL_EntityNum(i), false);
1137 case svc_spawnbaseline2:
1138 i = MSG_ReadShort ();
1139 // must use CL_EntityNum() to force cl.num_entities up
1140 CL_ParseBaseline (CL_EntityNum(i), true);
1142 case svc_spawnstatic:
1143 CL_ParseStatic (false);
1145 case svc_spawnstatic2:
1146 CL_ParseStatic (true);
1148 case svc_temp_entity:
1153 cl.paused = MSG_ReadByte ();
1161 i = MSG_ReadByte ();
1162 if (i <= cls.signon)
1163 Host_Error ("Received signon %i when at %i", i, cls.signon);
1168 case svc_killedmonster:
1169 cl.stats[STAT_MONSTERS]++;
1172 case svc_foundsecret:
1173 cl.stats[STAT_SECRETS]++;
1176 case svc_updatestat:
1177 i = MSG_ReadByte ();
1178 if (i < 0 || i >= MAX_CL_STATS)
1179 Host_Error ("svc_updatestat: %i is invalid", i);
1180 cl.stats[i] = MSG_ReadLong ();
1183 case svc_spawnstaticsound:
1184 CL_ParseStaticSound (false);
1187 case svc_spawnstaticsound2:
1188 CL_ParseStaticSound (true);
1192 cl.cdtrack = MSG_ReadByte ();
1193 cl.looptrack = MSG_ReadByte ();
1194 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1195 CDAudio_Play ((byte)cls.forcetrack, true);
1197 CDAudio_Play ((byte)cl.cdtrack, true);
1200 case svc_intermission:
1201 cl.intermission = 1;
1202 cl.completed_time = cl.time;
1203 // vid.recalc_refdef = true; // go to full screen
1207 cl.intermission = 2;
1208 cl.completed_time = cl.time;
1209 // vid.recalc_refdef = true; // go to full screen
1210 SCR_CenterPrint (MSG_ReadString ());
1214 cl.intermission = 3;
1215 cl.completed_time = cl.time;
1216 // vid.recalc_refdef = true; // go to full screen
1217 SCR_CenterPrint (MSG_ReadString ());
1220 case svc_sellscreen:
1221 Cmd_ExecuteString ("help", src_command);
1224 SHOWLMP_decodehide();
1227 SHOWLMP_decodeshow();
1230 R_SetSkyBox(MSG_ReadString());
1235 if (entitiesupdated)
1236 CL_EntityUpdateEnd();