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;
238 void CL_ParseEntityLump(char *entdata)
241 char key[128], value[4096];
244 FOG_clear(); // LordHavoc: no fog until set
245 skyname[0] = 0; // LordHavoc: no enviroment mapped sky until set
246 r_farclip.value = 6144; // LordHavoc: default farclip distance
250 data = COM_Parse(data);
252 return; // valid exit
253 if (com_token[0] != '{')
257 data = COM_Parse(data);
260 if (com_token[0] == '}')
261 return; // since we're just parsing the first ent (worldspawn), exit
262 strcpy(key, com_token);
263 while (key[strlen(key)-1] == ' ') // remove trailing spaces
264 key[strlen(key)-1] = 0;
265 data = COM_Parse(data);
268 strcpy(value, com_token);
269 if (!strcmp("sky", key))
271 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
273 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
275 else if (!strcmp("farclip", key))
277 r_farclip.value = atof(value);
278 if (r_farclip.value < 64)
279 r_farclip.value = 64;
281 else if (!strcmp("fog", key))
283 scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
286 else if (!strcmp("fog_density", key))
287 fog_density = atof(value);
288 else if (!strcmp("fog_red", key))
289 fog_red = atof(value);
290 else if (!strcmp("fog_green", key))
291 fog_green = atof(value);
292 else if (!strcmp("fog_blue", key))
293 fog_blue = atof(value);
294 else if (!strcmp("wad", key)) // for HalfLife maps
297 for (i = 0;i < 4096;i++)
298 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
304 // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
305 if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
307 else if (value[i] == ';' || value[i] == 0)
311 strcpy(wadname, "textures/");
312 strcat(wadname, &value[j]);
313 W_LoadTextureWadFile (wadname, false);
329 extern cvar_t demo_nehahra;
330 void CL_ParseServerInfo (void)
334 int nummodels, numsounds;
335 char model_precache[MAX_MODELS][MAX_QPATH];
336 char sound_precache[MAX_SOUNDS][MAX_QPATH];
338 Con_DPrintf ("Serverinfo packet received.\n");
340 // wipe the client_state_t struct
344 // parse protocol version number
346 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
348 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
351 Nehahrademcompatibility = false;
353 Nehahrademcompatibility = true;
354 if (cls.demoplayback && demo_nehahra.value)
355 Nehahrademcompatibility = true;
356 dpprotocol = i == DPPROTOCOL_VERSION;
359 cl.maxclients = MSG_ReadByte ();
360 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
362 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
365 cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
368 cl.gametype = MSG_ReadByte ();
370 // parse signon message
371 str = MSG_ReadString ();
372 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
374 // seperate the printfs so the server message can have a color
375 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
377 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");
378 Con_Printf ("%c%s\n", 2, str);
382 // first we go through and touch all of the precache data that still
383 // happens to be in the cache, so precaching something else doesn't
384 // needlessly purge it
388 memset (cl.model_precache, 0, sizeof(cl.model_precache));
389 for (nummodels=1 ; ; nummodels++)
391 str = MSG_ReadString ();
394 if (nummodels==MAX_MODELS)
396 Con_Printf ("Server sent too many model precaches\n");
399 if (strlen(str) >= MAX_QPATH)
400 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
401 strcpy (model_precache[nummodels], str);
402 Mod_TouchModel (str);
406 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
407 for (numsounds=1 ; ; numsounds++)
409 str = MSG_ReadString ();
412 if (numsounds==MAX_SOUNDS)
414 Con_Printf ("Server sent too many sound precaches\n");
417 if (strlen(str) >= MAX_QPATH)
418 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
419 strcpy (sound_precache[numsounds], str);
424 // now we try to load everything else until a cache allocation fails
427 for (i=1 ; i<nummodels ; i++)
429 isworldmodel = i == 1; // LordHavoc: first model is the world model
430 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
431 if (cl.model_precache[i] == NULL)
433 Con_Printf("Model %s not found\n", model_precache[i]);
436 CL_KeepaliveMessage ();
439 S_BeginPrecaching ();
440 for (i=1 ; i<numsounds ; i++)
442 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
443 CL_KeepaliveMessage ();
449 cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
453 Hunk_Check (); // make sure nothing is hurt
455 noclip_anglehack = false; // noclip is turned off at start
458 void CL_ValidateState(entity_state_t *s)
465 if (s->modelindex >= MAX_MODELS)
466 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
468 // colormap is client index + 1
469 if (s->colormap > cl.maxclients)
470 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
472 model = cl.model_precache[s->modelindex];
473 if (model && s->frame >= model->numframes)
475 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
484 Parse an entity update message from the server
485 If an entities model or origin changes from frame to frame, it must be
486 relinked. Other attributes can change without relinking.
489 byte entkill[MAX_EDICTS];
490 void CL_ParseUpdate (int bits)
495 if (cls.signon == SIGNONS - 1)
496 { // first update is the final signon stage
497 cls.signon = SIGNONS;
501 if (bits & U_MOREBITS)
502 bits |= (MSG_ReadByte()<<8);
503 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
505 bits |= MSG_ReadByte() << 16;
506 if (bits & U_EXTEND2)
507 bits |= MSG_ReadByte() << 24;
510 if (bits & U_LONGENTITY)
511 num = (unsigned) MSG_ReadShort ();
513 num = (unsigned) MSG_ReadByte ();
515 if (num >= MAX_EDICTS)
516 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
518 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
520 // mark as visible (no kill)
523 ent = CL_EntityNum (num);
525 ent->state_previous = ent->state_current;
529 if (!ent->state_current.active)
530 deltadie = true; // was not present in previous frame, leave hidden until next full update
533 ent->state_current = ent->state_baseline;
535 ent->state_current.time = cl.mtime[0];
537 ent->state_current.flags = 0;
538 ent->state_current.active = true;
539 if (bits & U_MODEL) ent->state_current.modelindex = (ent->state_current.modelindex & 0xFF00) | MSG_ReadByte();
540 if (bits & U_FRAME) ent->state_current.frame = (ent->state_current.frame & 0xFF00) | MSG_ReadByte();
541 if (bits & U_COLORMAP) ent->state_current.colormap = MSG_ReadByte();
542 if (bits & U_SKIN) ent->state_current.skin = MSG_ReadByte();
543 if (bits & U_EFFECTS) ent->state_current.effects = (ent->state_current.effects & 0xFF00) | MSG_ReadByte();
544 if (bits & U_ORIGIN1) ent->state_current.origin[0] = MSG_ReadCoord();
545 if (bits & U_ANGLE1) ent->state_current.angles[0] = MSG_ReadAngle();
546 if (bits & U_ORIGIN2) ent->state_current.origin[1] = MSG_ReadCoord();
547 if (bits & U_ANGLE2) ent->state_current.angles[1] = MSG_ReadAngle();
548 if (bits & U_ORIGIN3) ent->state_current.origin[2] = MSG_ReadCoord();
549 if (bits & U_ANGLE3) ent->state_current.angles[2] = MSG_ReadAngle();
550 if (bits & U_STEP) ent->state_current.flags |= RENDER_STEP;
551 if (bits & U_ALPHA) ent->state_current.alpha = MSG_ReadByte();
552 if (bits & U_SCALE) ent->state_current.scale = MSG_ReadByte();
553 if (bits & U_EFFECTS2) ent->state_current.effects = (ent->state_current.effects & 0x00FF) | (MSG_ReadByte() << 8);
554 if (bits & U_GLOWSIZE) ent->state_current.glowsize = MSG_ReadByte();
555 if (bits & U_GLOWCOLOR) ent->state_current.glowcolor = MSG_ReadByte();
556 if (bits & U_GLOWTRAIL) ent->state_current.flags |= RENDER_GLOWTRAIL;
557 if (bits & U_COLORMOD) ent->state_current.colormod = MSG_ReadByte();
558 if (bits & U_FRAME2) ent->state_current.frame = (ent->state_current.frame & 0x00FF) | (MSG_ReadByte() << 8);
559 if (bits & U_MODEL2) ent->state_current.modelindex = (ent->state_current.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
560 if (bits & U_VIEWMODEL) ent->state_current.flags |= RENDER_VIEWMODEL;
562 // LordHavoc: to allow playback of the Nehahra movie
563 if (Nehahrademcompatibility && (bits & U_EXTEND1))
565 // LordHavoc: evil format
566 int i = MSG_ReadFloat();
567 int j = MSG_ReadFloat() * 255.0f;
571 ent->state_current.effects |= EF_FULLBRIGHT;
574 ent->state_current.alpha = 0;
575 else if (j == 0 || j >= 255)
576 ent->state_current.alpha = 255;
578 ent->state_current.alpha = j;
584 ent->state_current.active = false;
588 CL_ValidateState(&ent->state_current);
591 if (!ent->state_current.active)
596 Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i %i\n", num, ent->state_previous.modelindex, ent->state_current.modelindex);
598 Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i\n", num, ent->state_previous.modelindex);
603 Con_Printf("CL_ParseUpdate: NULL model on %i: %i %i\n", num, ent->state_baseline.modelindex, ent->state_current.modelindex);
605 Con_Printf("CL_ParseUpdate: NULL model on %i: %i\n", num, ent->state_baseline.modelindex);
612 int entityupdatestart;
613 void CL_EntityUpdateBegin(int start)
615 if (start < 0 || start >= MAX_EDICTS)
616 Host_Error("CL_EntityUpdateBegin: start (%i) < 0 or >= MAX_EDICTS (%i)\n", start, MAX_EDICTS);
617 entityupdatestart = start;
618 memset(entkill, 1, MAX_EDICTS);
621 void CL_EntityUpdateEnd(int end)
624 if (end < 0 || end > MAX_EDICTS)
625 Host_Error("CL_EntityUpdateEnd: end (%i) < 0 or > MAX_EDICTS (%i)\n", end, MAX_EDICTS);
626 for (i = entityupdatestart;i < end;i++)
628 cl_entities[i].state_current.active = 0;
636 void CL_ParseBaseline (entity_t *ent, int largemodelindex)
640 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
641 ent->state_baseline.active = true;
643 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
645 ent->state_baseline.modelindex = MSG_ReadByte ();
646 ent->state_baseline.frame = MSG_ReadByte ();
647 ent->state_baseline.colormap = MSG_ReadByte();
648 ent->state_baseline.skin = MSG_ReadByte();
649 for (i = 0;i < 3;i++)
651 ent->state_baseline.origin[i] = MSG_ReadCoord ();
652 ent->state_baseline.angles[i] = MSG_ReadAngle ();
654 ent->state_baseline.alpha = 255;
655 ent->state_baseline.scale = 16;
656 ent->state_baseline.glowsize = 0;
657 ent->state_baseline.glowcolor = 254;
658 ent->state_baseline.colormod = 255;
659 ent->state_previous = ent->state_current = ent->state_baseline;
661 CL_ValidateState(&ent->state_baseline);
669 Server information pertaining to this client only
672 void CL_ParseClientdata (int bits)
677 if (bits & SU_EXTEND1)
678 bits |= (MSG_ReadByte() << 16);
679 if (bits & SU_EXTEND2)
680 bits |= (MSG_ReadByte() << 24);
682 if (bits & SU_VIEWHEIGHT)
683 cl.viewheight = MSG_ReadChar ();
685 cl.viewheight = DEFAULT_VIEWHEIGHT;
687 if (bits & SU_IDEALPITCH)
688 cl.idealpitch = MSG_ReadChar ();
692 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
693 for (i=0 ; i<3 ; i++)
695 if (bits & (SU_PUNCH1<<i) )
698 cl.punchangle[i] = MSG_ReadPreciseAngle();
700 cl.punchangle[i] = MSG_ReadChar();
703 cl.punchangle[i] = 0;
704 if (bits & (SU_PUNCHVEC1<<i))
705 cl.punchvector[i] = MSG_ReadFloatCoord();
707 cl.punchvector[i] = 0;
708 if (bits & (SU_VELOCITY1<<i) )
709 cl.mvelocity[0][i] = MSG_ReadChar()*16;
711 cl.mvelocity[0][i] = 0;
717 for (j=0 ; j<32 ; j++)
718 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
719 cl.item_gettime[j] = cl.time;
723 cl.onground = (bits & SU_ONGROUND) != 0;
724 cl.inwater = (bits & SU_INWATER) != 0;
726 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
727 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
728 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
729 cl.stats[STAT_HEALTH] = MSG_ReadShort();
730 cl.stats[STAT_AMMO] = MSG_ReadByte();
732 cl.stats[STAT_SHELLS] = MSG_ReadByte();
733 cl.stats[STAT_NAILS] = MSG_ReadByte();
734 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
735 cl.stats[STAT_CELLS] = MSG_ReadByte();
740 cl.stats[STAT_ACTIVEWEAPON] = i;
742 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
746 =====================
748 =====================
750 void CL_ParseStatic (int largemodelindex)
754 if (cl.num_statics >= MAX_STATIC_ENTITIES)
755 Host_Error ("Too many static entities");
756 ent = &cl_static_entities[cl.num_statics++];
757 CL_ParseBaseline (ent, largemodelindex);
759 // copy it to the current state
760 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
761 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
762 ent->render.framelerp = 0;
763 ent->render.lerp_starttime = -1;
764 // make torchs play out of sync
765 ent->render.frame1start = ent->render.frame2start = -(rand() & 32767);
766 ent->render.colormap = -1; // no special coloring
767 ent->render.skinnum = ent->state_baseline.skin;
768 ent->render.effects = ent->state_baseline.effects;
769 ent->render.alpha = 1;
770 ent->render.scale = 1;
771 ent->render.alpha = 1;
772 ent->render.glowsize = 0;
773 ent->render.glowcolor = 254;
774 ent->render.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
776 VectorCopy (ent->state_baseline.origin, ent->render.origin);
777 VectorCopy (ent->state_baseline.angles, ent->render.angles);
778 // R_AddEfrags (ent);
786 void CL_ParseStaticSound (void)
789 int sound_num, vol, atten;
792 sound_num = MSG_ReadByte ();
793 vol = MSG_ReadByte ();
794 atten = MSG_ReadByte ();
796 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
799 void CL_ParseEffect (void)
802 int modelindex, startframe, framecount, framerate;
805 modelindex = MSG_ReadByte ();
806 startframe = MSG_ReadByte ();
807 framecount = MSG_ReadByte ();
808 framerate = MSG_ReadByte ();
810 CL_Effect(org, modelindex, startframe, framecount, framerate);
813 void CL_ParseEffect2 (void)
816 int modelindex, startframe, framecount, framerate;
819 modelindex = MSG_ReadShort ();
820 startframe = MSG_ReadByte ();
821 framecount = MSG_ReadByte ();
822 framerate = MSG_ReadByte ();
824 CL_Effect(org, modelindex, startframe, framecount, framerate);
828 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
830 extern void SHOWLMP_decodehide();
831 extern void SHOWLMP_decodeshow();
832 extern void R_SetSkyBox(char* sky);
836 =====================
837 CL_ParseServerMessage
838 =====================
840 void CL_ParseServerMessage (void)
845 char *cmdlogname[32], *temp;
846 int cmdindex, cmdcount = 0;
849 // if recording demos, copy the message out
851 if (cl_shownet.value == 1)
853 Con_Printf ("%i ",net_message.cursize);
856 else if (cl_shownet.value == 2)
858 Con_Printf ("------------------\n");
862 cl.onground = false; // unless the server says otherwise
873 Host_Error ("CL_ParseServerMessage: Bad server message");
875 cmd = MSG_ReadByte ();
879 SHOWNET("END OF MESSAGE");
880 break; // end of message
883 cmdindex = cmdcount & 31;
885 cmdlog[cmdindex] = cmd;
887 // if the high bit of the command byte is set, it is a fast update
890 // 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)
892 cmdlogname[cmdindex] = temp;
893 SHOWNET("fast update");
894 CL_ParseUpdate (cmd&127);
898 SHOWNET(svc_strings[cmd]);
899 cmdlogname[cmdindex] = svc_strings[cmd];
900 if (!cmdlogname[cmdindex])
902 // 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)
904 cmdlogname[cmdindex] = temp;
912 char description[32*64], temp[64];
914 strcpy(description, "packet dump: ");
918 count = cmdcount - i;
922 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
923 strcat(description, temp);
928 description[strlen(description)-1] = '\n'; // replace the last space with a newline
929 Con_Printf(description);
930 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
935 // Con_Printf ("svc_nop\n");
939 // handle old protocols which do not have entity update ranges
940 CL_EntityUpdateBegin(0);
942 cl.mtime[1] = cl.mtime[0];
943 cl.mtime[0] = MSG_ReadFloat ();
947 i = MSG_ReadShort ();
948 CL_ParseClientdata (i);
953 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
954 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
955 Nehahrademcompatibility = false;
957 Nehahrademcompatibility = true;
958 if (cls.demoplayback && demo_nehahra.value)
959 Nehahrademcompatibility = true;
960 dpprotocol = i == DPPROTOCOL_VERSION;
964 Host_EndGame ("Server disconnected\n");
967 Con_Printf ("%s", MSG_ReadString ());
970 case svc_centerprint:
971 SCR_CenterPrint (MSG_ReadString ());
975 Cbuf_AddText (MSG_ReadString ());
983 CL_ParseServerInfo ();
984 vid.recalc_refdef = true; // leave intermission full screen
988 for (i=0 ; i<3 ; i++)
989 cl.viewangles[i] = MSG_ReadAngle ();
993 cl.viewentity = MSG_ReadShort ();
998 if (i >= MAX_LIGHTSTYLES)
999 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1000 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1001 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1002 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1006 CL_ParseStartSoundPacket(false);
1010 CL_ParseStartSoundPacket(true);
1014 i = MSG_ReadShort();
1015 S_StopSound(i>>3, i&7);
1018 case svc_updatename:
1019 i = MSG_ReadByte ();
1020 if (i >= cl.maxclients)
1021 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1022 strcpy (cl.scores[i].name, MSG_ReadString ());
1025 case svc_updatefrags:
1026 i = MSG_ReadByte ();
1027 if (i >= cl.maxclients)
1028 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1029 cl.scores[i].frags = MSG_ReadShort ();
1032 case svc_updatecolors:
1033 i = MSG_ReadByte ();
1034 if (i >= cl.maxclients)
1035 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1036 cl.scores[i].colors = MSG_ReadByte ();
1040 R_ParseParticleEffect ();
1051 case svc_spawnbaseline:
1052 i = MSG_ReadShort ();
1053 // must use CL_EntityNum() to force cl.num_entities up
1054 CL_ParseBaseline (CL_EntityNum(i), false);
1056 case svc_spawnbaseline2:
1057 i = MSG_ReadShort ();
1058 // must use CL_EntityNum() to force cl.num_entities up
1059 CL_ParseBaseline (CL_EntityNum(i), false);
1061 case svc_spawnstatic:
1062 CL_ParseStatic (false);
1064 case svc_spawnstatic2:
1065 CL_ParseStatic (true);
1067 case svc_temp_entity:
1072 cl.paused = MSG_ReadByte ();
1080 i = MSG_ReadByte ();
1081 if (i <= cls.signon)
1082 Host_Error ("Received signon %i when at %i", i, cls.signon);
1087 case svc_killedmonster:
1088 cl.stats[STAT_MONSTERS]++;
1091 case svc_foundsecret:
1092 cl.stats[STAT_SECRETS]++;
1095 case svc_updatestat:
1096 i = MSG_ReadByte ();
1097 if (i < 0 || i >= MAX_CL_STATS)
1098 Host_Error ("svc_updatestat: %i is invalid", i);
1099 cl.stats[i] = MSG_ReadLong ();
1102 case svc_spawnstaticsound:
1103 CL_ParseStaticSound ();
1107 cl.cdtrack = MSG_ReadByte ();
1108 cl.looptrack = MSG_ReadByte ();
1109 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1110 CDAudio_Play ((byte)cls.forcetrack, true);
1112 CDAudio_Play ((byte)cl.cdtrack, true);
1115 case svc_intermission:
1116 cl.intermission = 1;
1117 cl.completed_time = cl.time;
1118 vid.recalc_refdef = true; // go to full screen
1122 cl.intermission = 2;
1123 cl.completed_time = cl.time;
1124 vid.recalc_refdef = true; // go to full screen
1125 SCR_CenterPrint (MSG_ReadString ());
1129 cl.intermission = 3;
1130 cl.completed_time = cl.time;
1131 vid.recalc_refdef = true; // go to full screen
1132 SCR_CenterPrint (MSG_ReadString ());
1135 case svc_sellscreen:
1136 Cmd_ExecuteString ("help", src_command);
1139 SHOWLMP_decodehide();
1142 SHOWLMP_decodeshow();
1144 case svc_entitiesbegin:
1145 // the beginning of an entity update range
1146 CL_EntityUpdateBegin((unsigned) MSG_ReadShort());
1148 case svc_entitiesend:
1149 // the end of an entity update range
1150 CL_EntityUpdateEnd((unsigned) MSG_ReadShort());
1157 CL_EntityUpdateEnd(MAX_EDICTS);