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
85 "svc_effect", // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
86 "svc_effect2", // [vector] org [short] modelindex [byte] startframe [byte] framecount [byte] framerate
89 //=============================================================================
91 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
92 qboolean dpprotocol; // LordHavoc: whether or not the current network stream is the enhanced DarkPlaces protocol
98 This error checks and tracks the total number of entities
101 entity_t *CL_EntityNum (int num)
104 if (num >= cl.num_entities)
106 if (num >= MAX_EDICTS)
107 Host_Error ("CL_EntityNum: %i is an invalid number",num);
108 cl.num_entities = num;
109 // while (cl.num_entities <= num)
111 // cl_entities[cl.num_entities].colormap = -1; // no special coloring
112 // cl.num_entities++;
116 if (num >= MAX_EDICTS)
117 Host_Error ("CL_EntityNum: %i is an invalid number",num);
119 return &cl_entities[num];
125 CL_ParseStartSoundPacket
128 void CL_ParseStartSoundPacket(int largesoundindex)
138 field_mask = MSG_ReadByte();
140 if (field_mask & SND_VOLUME)
141 volume = MSG_ReadByte ();
143 volume = DEFAULT_SOUND_PACKET_VOLUME;
145 if (field_mask & SND_ATTENUATION)
146 attenuation = MSG_ReadByte () / 64.0;
148 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
150 channel = MSG_ReadShort ();
152 sound_num = (unsigned short) MSG_ReadShort ();
154 sound_num = MSG_ReadByte ();
156 if (sound_num >= MAX_SOUNDS)
157 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
162 if (ent > MAX_EDICTS)
163 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
165 for (i=0 ; i<3 ; i++)
166 pos[i] = MSG_ReadCoord ();
168 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
175 When the client is taking a long time to load stuff, send keepalive messages
176 so the server doesn't disconnect.
179 void CL_KeepaliveMessage (void)
182 static float lastmsg;
188 return; // no need if server is local
189 if (cls.demoplayback)
192 // read messages from server, should just be nops
194 memcpy (olddata, net_message.data, net_message.cursize);
198 ret = CL_GetMessage ();
202 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
204 break; // nothing waiting
206 Host_Error ("CL_KeepaliveMessage: received a message");
209 if (MSG_ReadByte() != svc_nop)
210 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
216 memcpy (net_message.data, olddata, net_message.cursize);
219 time = Sys_FloatTime ();
220 if (time - lastmsg < 5)
225 Con_Printf ("--> client to server keepalive\n");
227 MSG_WriteByte (&cls.message, clc_nop);
228 NET_SendMessage (cls.netcon, &cls.message);
229 SZ_Clear (&cls.message);
232 extern qboolean isworldmodel;
233 extern char skyname[];
234 extern void R_SetSkyBox (char *sky);
235 extern void FOG_clear();
236 extern cvar_t r_farclip;
237 extern qboolean hlbsp;
239 void CL_ParseEntityLump(char *entdata)
242 char key[128], value[4096];
245 FOG_clear(); // LordHavoc: no fog until set
246 skyname[0] = 0; // LordHavoc: no enviroment mapped sky until set
247 r_farclip.value = 6144; // LordHavoc: default farclip distance
251 data = COM_Parse(data);
253 return; // valid exit
254 if (com_token[0] != '{')
258 data = COM_Parse(data);
261 if (com_token[0] == '}')
262 return; // since we're just parsing the first ent (worldspawn), exit
263 strcpy(key, com_token);
264 while (key[strlen(key)-1] == ' ') // remove trailing spaces
265 key[strlen(key)-1] = 0;
266 data = COM_Parse(data);
269 strcpy(value, com_token);
270 if (!strcmp("sky", key))
272 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
274 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
276 else if (!strcmp("farclip", key))
278 r_farclip.value = atof(value);
279 if (r_farclip.value < 64)
280 r_farclip.value = 64;
282 else if (!strcmp("fog", key))
284 scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
287 else if (!strcmp("fog_density", key))
288 fog_density = atof(value);
289 else if (!strcmp("fog_red", key))
290 fog_red = atof(value);
291 else if (!strcmp("fog_green", key))
292 fog_green = atof(value);
293 else if (!strcmp("fog_blue", key))
294 fog_blue = atof(value);
295 else if (!strcmp("wad", key)) // for HalfLife maps
300 for (i = 0;i < 4096;i++)
301 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
307 // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
308 if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
310 else if (value[i] == ';' || value[i] == 0)
314 strcpy(wadname, "textures/");
315 strcat(wadname, &value[j]);
316 W_LoadTextureWadFile (wadname, false);
333 extern cvar_t demo_nehahra;
334 void CL_ParseServerInfo (void)
338 int nummodels, numsounds;
339 char model_precache[MAX_MODELS][MAX_QPATH];
340 char sound_precache[MAX_SOUNDS][MAX_QPATH];
342 Con_DPrintf ("Serverinfo packet received.\n");
344 // wipe the client_state_t struct
348 // parse protocol version number
350 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
352 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
355 Nehahrademcompatibility = false;
357 Nehahrademcompatibility = true;
358 if (cls.demoplayback && demo_nehahra.value)
359 Nehahrademcompatibility = true;
360 dpprotocol = i == DPPROTOCOL_VERSION;
363 cl.maxclients = MSG_ReadByte ();
364 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
366 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
369 cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
372 cl.gametype = MSG_ReadByte ();
374 // parse signon message
375 str = MSG_ReadString ();
376 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
378 // seperate the printfs so the server message can have a color
379 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
381 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");
382 Con_Printf ("%c%s\n", 2, str);
386 // first we go through and touch all of the precache data that still
387 // happens to be in the cache, so precaching something else doesn't
388 // needlessly purge it
392 memset (cl.model_precache, 0, sizeof(cl.model_precache));
393 for (nummodels=1 ; ; nummodels++)
395 str = MSG_ReadString ();
398 if (nummodels==MAX_MODELS)
400 Con_Printf ("Server sent too many model precaches\n");
403 if (strlen(str) >= MAX_QPATH)
404 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
405 strcpy (model_precache[nummodels], str);
406 Mod_TouchModel (str);
410 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
411 for (numsounds=1 ; ; numsounds++)
413 str = MSG_ReadString ();
416 if (numsounds==MAX_SOUNDS)
418 Con_Printf ("Server sent too many sound precaches\n");
421 if (strlen(str) >= MAX_QPATH)
422 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
423 strcpy (sound_precache[numsounds], str);
428 // now we try to load everything else until a cache allocation fails
431 for (i=1 ; i<nummodels ; i++)
433 isworldmodel = i == 1; // LordHavoc: first model is the world model
434 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
435 if (cl.model_precache[i] == NULL)
437 Con_Printf("Model %s not found\n", model_precache[i]);
440 CL_KeepaliveMessage ();
443 S_BeginPrecaching ();
444 for (i=1 ; i<numsounds ; i++)
446 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
447 CL_KeepaliveMessage ();
453 cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
457 Hunk_Check (); // make sure nothing is hurt
459 noclip_anglehack = false; // noclip is turned off at start
462 void CL_ValidateState(entity_state_t *s)
469 if (s->modelindex >= MAX_MODELS)
470 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
472 // colormap is client index + 1
473 if (s->colormap > cl.maxclients)
474 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
476 model = cl.model_precache[s->modelindex];
477 if (model && s->frame >= model->numframes)
479 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
488 Parse an entity update message from the server
489 If an entities model or origin changes from frame to frame, it must be
490 relinked. Other attributes can change without relinking.
493 byte entkill[MAX_EDICTS];
494 void CL_ParseUpdate (int bits)
499 if (cls.signon == SIGNONS - 1)
500 { // first update is the final signon stage
501 cls.signon = SIGNONS;
505 if (bits & U_MOREBITS)
506 bits |= (MSG_ReadByte()<<8);
507 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
509 bits |= MSG_ReadByte() << 16;
510 if (bits & U_EXTEND2)
511 bits |= MSG_ReadByte() << 24;
514 if (bits & U_LONGENTITY)
515 num = (unsigned) MSG_ReadShort ();
517 num = (unsigned) MSG_ReadByte ();
519 if (num >= MAX_EDICTS)
520 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
522 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
524 // mark as visible (no kill)
527 ent = CL_EntityNum (num);
529 ent->state_previous = ent->state_current;
533 if (!ent->state_current.active)
534 deltadie = true; // was not present in previous frame, leave hidden until next full update
537 ent->state_current = ent->state_baseline;
539 ent->state_current.time = cl.mtime[0];
541 ent->state_current.flags = 0;
542 ent->state_current.active = true;
543 if (bits & U_MODEL) ent->state_current.modelindex = (ent->state_current.modelindex & 0xFF00) | MSG_ReadByte();
544 if (bits & U_FRAME) ent->state_current.frame = (ent->state_current.frame & 0xFF00) | MSG_ReadByte();
545 if (bits & U_COLORMAP) ent->state_current.colormap = MSG_ReadByte();
546 if (bits & U_SKIN) ent->state_current.skin = MSG_ReadByte();
547 if (bits & U_EFFECTS) ent->state_current.effects = (ent->state_current.effects & 0xFF00) | MSG_ReadByte();
548 if (bits & U_ORIGIN1) ent->state_current.origin[0] = MSG_ReadCoord();
549 if (bits & U_ANGLE1) ent->state_current.angles[0] = MSG_ReadAngle();
550 if (bits & U_ORIGIN2) ent->state_current.origin[1] = MSG_ReadCoord();
551 if (bits & U_ANGLE2) ent->state_current.angles[1] = MSG_ReadAngle();
552 if (bits & U_ORIGIN3) ent->state_current.origin[2] = MSG_ReadCoord();
553 if (bits & U_ANGLE3) ent->state_current.angles[2] = MSG_ReadAngle();
554 if (bits & U_STEP) ent->state_current.flags |= RENDER_STEP;
555 if (bits & U_ALPHA) ent->state_current.alpha = MSG_ReadByte();
556 if (bits & U_SCALE) ent->state_current.scale = MSG_ReadByte();
557 if (bits & U_EFFECTS2) ent->state_current.effects = (ent->state_current.effects & 0x00FF) | (MSG_ReadByte() << 8);
558 if (bits & U_GLOWSIZE) ent->state_current.glowsize = MSG_ReadByte();
559 if (bits & U_GLOWCOLOR) ent->state_current.glowcolor = MSG_ReadByte();
560 if (bits & U_GLOWTRAIL) ent->state_current.flags |= RENDER_GLOWTRAIL;
561 if (bits & U_COLORMOD) ent->state_current.colormod = MSG_ReadByte();
562 if (bits & U_FRAME2) ent->state_current.frame = (ent->state_current.frame & 0x00FF) | (MSG_ReadByte() << 8);
563 if (bits & U_MODEL2) ent->state_current.modelindex = (ent->state_current.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
564 if (bits & U_VIEWMODEL) ent->state_current.flags |= RENDER_VIEWMODEL;
566 // LordHavoc: to allow playback of the Nehahra movie
567 if (Nehahrademcompatibility && (bits & U_EXTEND1))
569 // LordHavoc: evil format
570 int i = MSG_ReadFloat();
571 int j = MSG_ReadFloat() * 255.0f;
575 ent->state_current.effects |= EF_FULLBRIGHT;
578 ent->state_current.alpha = 0;
579 else if (j == 0 || j >= 255)
580 ent->state_current.alpha = 255;
582 ent->state_current.alpha = j;
588 ent->state_current.active = false;
592 CL_ValidateState(&ent->state_current);
595 if (!ent->state_current.active)
600 Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i %i\n", num, ent->state_previous.modelindex, ent->state_current.modelindex);
602 Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i\n", num, ent->state_previous.modelindex);
607 Con_Printf("CL_ParseUpdate: NULL model on %i: %i %i\n", num, ent->state_baseline.modelindex, ent->state_current.modelindex);
609 Con_Printf("CL_ParseUpdate: NULL model on %i: %i\n", num, ent->state_baseline.modelindex);
616 void CL_EntityUpdateSetup()
618 memset(entkill, 1, MAX_EDICTS);
621 int entityupdatestart;
622 void CL_EntityUpdateBegin(int start)
624 if (start < 0 || start >= MAX_EDICTS)
625 Host_Error("CL_EntityUpdateBegin: start (%i) < 0 or >= MAX_EDICTS (%i)\n", start, MAX_EDICTS);
626 entityupdatestart = start;
629 void CL_EntityUpdateEnd(int end)
632 if (end < 0 || end > MAX_EDICTS)
633 Host_Error("CL_EntityUpdateEnd: end (%i) < 0 or > MAX_EDICTS (%i)\n", end, MAX_EDICTS);
634 for (i = entityupdatestart;i < end;i++)
636 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
644 void CL_ParseBaseline (entity_t *ent, int largemodelindex)
648 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
649 ent->state_baseline.active = true;
651 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
653 ent->state_baseline.modelindex = MSG_ReadByte ();
654 ent->state_baseline.frame = MSG_ReadByte ();
655 ent->state_baseline.colormap = MSG_ReadByte();
656 ent->state_baseline.skin = MSG_ReadByte();
657 for (i = 0;i < 3;i++)
659 ent->state_baseline.origin[i] = MSG_ReadCoord ();
660 ent->state_baseline.angles[i] = MSG_ReadAngle ();
662 ent->state_baseline.alpha = 255;
663 ent->state_baseline.scale = 16;
664 ent->state_baseline.glowsize = 0;
665 ent->state_baseline.glowcolor = 254;
666 ent->state_baseline.colormod = 255;
667 ent->state_previous = ent->state_current = ent->state_baseline;
669 CL_ValidateState(&ent->state_baseline);
677 Server information pertaining to this client only
680 void CL_ParseClientdata (int bits)
685 if (bits & SU_EXTEND1)
686 bits |= (MSG_ReadByte() << 16);
687 if (bits & SU_EXTEND2)
688 bits |= (MSG_ReadByte() << 24);
690 if (bits & SU_VIEWHEIGHT)
691 cl.viewheight = MSG_ReadChar ();
693 cl.viewheight = DEFAULT_VIEWHEIGHT;
695 if (bits & SU_IDEALPITCH)
696 cl.idealpitch = MSG_ReadChar ();
700 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
701 for (i=0 ; i<3 ; i++)
703 if (bits & (SU_PUNCH1<<i) )
706 cl.punchangle[i] = MSG_ReadPreciseAngle();
708 cl.punchangle[i] = MSG_ReadChar();
711 cl.punchangle[i] = 0;
712 if (bits & (SU_PUNCHVEC1<<i))
713 cl.punchvector[i] = MSG_ReadFloatCoord();
715 cl.punchvector[i] = 0;
716 if (bits & (SU_VELOCITY1<<i) )
717 cl.mvelocity[0][i] = MSG_ReadChar()*16;
719 cl.mvelocity[0][i] = 0;
725 for (j=0 ; j<32 ; j++)
726 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
727 cl.item_gettime[j] = cl.time;
731 cl.onground = (bits & SU_ONGROUND) != 0;
732 cl.inwater = (bits & SU_INWATER) != 0;
734 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
735 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
736 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
737 cl.stats[STAT_HEALTH] = MSG_ReadShort();
738 cl.stats[STAT_AMMO] = MSG_ReadByte();
740 cl.stats[STAT_SHELLS] = MSG_ReadByte();
741 cl.stats[STAT_NAILS] = MSG_ReadByte();
742 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
743 cl.stats[STAT_CELLS] = MSG_ReadByte();
748 cl.stats[STAT_ACTIVEWEAPON] = i;
750 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
754 =====================
756 =====================
758 void CL_ParseStatic (int largemodelindex)
762 if (cl.num_statics >= MAX_STATIC_ENTITIES)
763 Host_Error ("Too many static entities");
764 ent = &cl_static_entities[cl.num_statics++];
765 CL_ParseBaseline (ent, largemodelindex);
767 // copy it to the current state
768 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
769 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
770 ent->render.framelerp = 0;
771 ent->render.lerp_starttime = -1;
772 // make torchs play out of sync
773 ent->render.frame1start = ent->render.frame2start = -(rand() & 32767);
774 ent->render.colormap = -1; // no special coloring
775 ent->render.skinnum = ent->state_baseline.skin;
776 ent->render.effects = ent->state_baseline.effects;
777 ent->render.alpha = 1;
778 ent->render.scale = 1;
779 ent->render.alpha = 1;
780 ent->render.glowsize = 0;
781 ent->render.glowcolor = 254;
782 ent->render.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
784 VectorCopy (ent->state_baseline.origin, ent->render.origin);
785 VectorCopy (ent->state_baseline.angles, ent->render.angles);
786 // R_AddEfrags (ent);
794 void CL_ParseStaticSound (void)
797 int sound_num, vol, atten;
800 sound_num = MSG_ReadByte ();
801 vol = MSG_ReadByte ();
802 atten = MSG_ReadByte ();
804 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
807 void CL_ParseEffect (void)
810 int modelindex, startframe, framecount, framerate;
813 modelindex = MSG_ReadByte ();
814 startframe = MSG_ReadByte ();
815 framecount = MSG_ReadByte ();
816 framerate = MSG_ReadByte ();
818 CL_Effect(org, modelindex, startframe, framecount, framerate);
821 void CL_ParseEffect2 (void)
824 int modelindex, startframe, framecount, framerate;
827 modelindex = MSG_ReadShort ();
828 startframe = MSG_ReadByte ();
829 framecount = MSG_ReadByte ();
830 framerate = MSG_ReadByte ();
832 CL_Effect(org, modelindex, startframe, framecount, framerate);
836 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
838 extern void SHOWLMP_decodehide();
839 extern void SHOWLMP_decodeshow();
840 extern void R_SetSkyBox(char* sky);
844 =====================
845 CL_ParseServerMessage
846 =====================
848 void CL_ParseServerMessage (void)
853 char *cmdlogname[32], *temp;
854 int cmdindex, cmdcount = 0;
857 // if recording demos, copy the message out
859 if (cl_shownet.value == 1)
861 Con_Printf ("%i ",net_message.cursize);
864 else if (cl_shownet.value == 2)
866 Con_Printf ("------------------\n");
870 cl.onground = false; // unless the server says otherwise
877 CL_EntityUpdateSetup();
882 Host_Error ("CL_ParseServerMessage: Bad server message");
884 cmd = MSG_ReadByte ();
888 SHOWNET("END OF MESSAGE");
889 break; // end of message
892 cmdindex = cmdcount & 31;
894 cmdlog[cmdindex] = cmd;
896 // if the high bit of the command byte is set, it is a fast update
899 // 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)
901 cmdlogname[cmdindex] = temp;
902 SHOWNET("fast update");
903 CL_ParseUpdate (cmd&127);
907 SHOWNET(svc_strings[cmd]);
908 cmdlogname[cmdindex] = svc_strings[cmd];
909 if (!cmdlogname[cmdindex])
911 // 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)
913 cmdlogname[cmdindex] = temp;
921 char description[32*64], temp[64];
923 strcpy(description, "packet dump: ");
927 count = cmdcount - i;
931 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
932 strcat(description, temp);
937 description[strlen(description)-1] = '\n'; // replace the last space with a newline
938 Con_Printf(description);
939 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
944 // Con_Printf ("svc_nop\n");
948 // handle old protocols which do not have entity update ranges
949 CL_EntityUpdateBegin(1);
951 cl.mtime[1] = cl.mtime[0];
952 cl.mtime[0] = MSG_ReadFloat ();
956 i = MSG_ReadShort ();
957 CL_ParseClientdata (i);
962 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
963 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
964 Nehahrademcompatibility = false;
966 Nehahrademcompatibility = true;
967 if (cls.demoplayback && demo_nehahra.value)
968 Nehahrademcompatibility = true;
969 dpprotocol = i == DPPROTOCOL_VERSION;
973 Host_EndGame ("Server disconnected\n");
976 Con_Printf ("%s", MSG_ReadString ());
979 case svc_centerprint:
980 SCR_CenterPrint (MSG_ReadString ());
984 Cbuf_AddText (MSG_ReadString ());
992 CL_ParseServerInfo ();
993 vid.recalc_refdef = true; // leave intermission full screen
997 for (i=0 ; i<3 ; i++)
998 cl.viewangles[i] = MSG_ReadAngle ();
1002 cl.viewentity = MSG_ReadShort ();
1005 case svc_lightstyle:
1006 i = MSG_ReadByte ();
1007 if (i >= MAX_LIGHTSTYLES)
1008 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1009 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1010 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1011 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1015 CL_ParseStartSoundPacket(false);
1019 CL_ParseStartSoundPacket(true);
1023 i = MSG_ReadShort();
1024 S_StopSound(i>>3, i&7);
1027 case svc_updatename:
1028 i = MSG_ReadByte ();
1029 if (i >= cl.maxclients)
1030 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1031 strcpy (cl.scores[i].name, MSG_ReadString ());
1034 case svc_updatefrags:
1035 i = MSG_ReadByte ();
1036 if (i >= cl.maxclients)
1037 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1038 cl.scores[i].frags = MSG_ReadShort ();
1041 case svc_updatecolors:
1042 i = MSG_ReadByte ();
1043 if (i >= cl.maxclients)
1044 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1045 cl.scores[i].colors = MSG_ReadByte ();
1049 R_ParseParticleEffect ();
1060 case svc_spawnbaseline:
1061 i = MSG_ReadShort ();
1062 // must use CL_EntityNum() to force cl.num_entities up
1063 CL_ParseBaseline (CL_EntityNum(i), false);
1065 case svc_spawnbaseline2:
1066 i = MSG_ReadShort ();
1067 // must use CL_EntityNum() to force cl.num_entities up
1068 CL_ParseBaseline (CL_EntityNum(i), false);
1070 case svc_spawnstatic:
1071 CL_ParseStatic (false);
1073 case svc_spawnstatic2:
1074 CL_ParseStatic (true);
1076 case svc_temp_entity:
1081 cl.paused = MSG_ReadByte ();
1089 i = MSG_ReadByte ();
1090 if (i <= cls.signon)
1091 Host_Error ("Received signon %i when at %i", i, cls.signon);
1096 case svc_killedmonster:
1097 cl.stats[STAT_MONSTERS]++;
1100 case svc_foundsecret:
1101 cl.stats[STAT_SECRETS]++;
1104 case svc_updatestat:
1105 i = MSG_ReadByte ();
1106 if (i < 0 || i >= MAX_CL_STATS)
1107 Host_Error ("svc_updatestat: %i is invalid", i);
1108 cl.stats[i] = MSG_ReadLong ();
1111 case svc_spawnstaticsound:
1112 CL_ParseStaticSound ();
1116 cl.cdtrack = MSG_ReadByte ();
1117 cl.looptrack = MSG_ReadByte ();
1118 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1119 CDAudio_Play ((byte)cls.forcetrack, true);
1121 CDAudio_Play ((byte)cl.cdtrack, true);
1124 case svc_intermission:
1125 cl.intermission = 1;
1126 cl.completed_time = cl.time;
1127 vid.recalc_refdef = true; // go to full screen
1131 cl.intermission = 2;
1132 cl.completed_time = cl.time;
1133 vid.recalc_refdef = true; // go to full screen
1134 SCR_CenterPrint (MSG_ReadString ());
1138 cl.intermission = 3;
1139 cl.completed_time = cl.time;
1140 vid.recalc_refdef = true; // go to full screen
1141 SCR_CenterPrint (MSG_ReadString ());
1144 case svc_sellscreen:
1145 Cmd_ExecuteString ("help", src_command);
1148 SHOWLMP_decodehide();
1151 SHOWLMP_decodeshow();
1153 case svc_entitiesbegin:
1154 // the beginning of an entity update range
1155 CL_EntityUpdateBegin((unsigned) MSG_ReadShort());
1157 case svc_entitiesend:
1158 // the end of an entity update range
1159 CL_EntityUpdateEnd((unsigned) MSG_ReadShort());
1166 CL_EntityUpdateEnd(MAX_EDICTS);