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
299 for (i = 0;i < 4096;i++)
300 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
306 // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
307 if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
309 else if (value[i] == ';' || value[i] == 0)
313 strcpy(wadname, "textures/");
314 strcat(wadname, &value[j]);
315 W_LoadTextureWadFile (wadname, false);
332 extern cvar_t demo_nehahra;
333 void CL_ParseServerInfo (void)
337 int nummodels, numsounds;
338 char model_precache[MAX_MODELS][MAX_QPATH];
339 char sound_precache[MAX_SOUNDS][MAX_QPATH];
341 Con_DPrintf ("Serverinfo packet received.\n");
343 // wipe the client_state_t struct
347 // parse protocol version number
349 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
351 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
354 Nehahrademcompatibility = false;
356 Nehahrademcompatibility = true;
357 if (cls.demoplayback && demo_nehahra.value)
358 Nehahrademcompatibility = true;
359 dpprotocol = i == DPPROTOCOL_VERSION;
362 cl.maxclients = MSG_ReadByte ();
363 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
365 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
368 cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
371 cl.gametype = MSG_ReadByte ();
373 // parse signon message
374 str = MSG_ReadString ();
375 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
377 // seperate the printfs so the server message can have a color
378 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
380 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");
381 Con_Printf ("%c%s\n", 2, str);
385 // first we go through and touch all of the precache data that still
386 // happens to be in the cache, so precaching something else doesn't
387 // needlessly purge it
391 memset (cl.model_precache, 0, sizeof(cl.model_precache));
392 for (nummodels=1 ; ; nummodels++)
394 str = MSG_ReadString ();
397 if (nummodels==MAX_MODELS)
399 Con_Printf ("Server sent too many model precaches\n");
402 if (strlen(str) >= MAX_QPATH)
403 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
404 strcpy (model_precache[nummodels], str);
405 Mod_TouchModel (str);
409 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
410 for (numsounds=1 ; ; numsounds++)
412 str = MSG_ReadString ();
415 if (numsounds==MAX_SOUNDS)
417 Con_Printf ("Server sent too many sound 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 (sound_precache[numsounds], str);
427 // now we try to load everything else until a cache allocation fails
430 for (i=1 ; i<nummodels ; i++)
432 isworldmodel = i == 1; // LordHavoc: first model is the world model
433 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
434 if (cl.model_precache[i] == NULL)
436 Con_Printf("Model %s not found\n", model_precache[i]);
439 CL_KeepaliveMessage ();
442 S_BeginPrecaching ();
443 for (i=1 ; i<numsounds ; i++)
445 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
446 CL_KeepaliveMessage ();
452 cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
456 Hunk_Check (); // make sure nothing is hurt
458 noclip_anglehack = false; // noclip is turned off at start
461 void CL_ValidateState(entity_state_t *s)
468 if (s->modelindex >= MAX_MODELS)
469 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
471 // colormap is client index + 1
472 if (s->colormap > cl.maxclients)
473 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
475 model = cl.model_precache[s->modelindex];
476 if (model && s->frame >= model->numframes)
478 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
487 Parse an entity update message from the server
488 If an entities model or origin changes from frame to frame, it must be
489 relinked. Other attributes can change without relinking.
492 byte entkill[MAX_EDICTS];
493 void CL_ParseUpdate (int bits)
498 if (cls.signon == SIGNONS - 1)
499 { // first update is the final signon stage
500 cls.signon = SIGNONS;
504 if (bits & U_MOREBITS)
505 bits |= (MSG_ReadByte()<<8);
506 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
508 bits |= MSG_ReadByte() << 16;
509 if (bits & U_EXTEND2)
510 bits |= MSG_ReadByte() << 24;
513 if (bits & U_LONGENTITY)
514 num = (unsigned) MSG_ReadShort ();
516 num = (unsigned) MSG_ReadByte ();
518 if (num >= MAX_EDICTS)
519 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
521 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
523 // mark as visible (no kill)
526 ent = CL_EntityNum (num);
528 ent->state_previous = ent->state_current;
532 if (!ent->state_current.active)
533 deltadie = true; // was not present in previous frame, leave hidden until next full update
536 ent->state_current = ent->state_baseline;
538 ent->state_current.time = cl.mtime[0];
540 ent->state_current.flags = 0;
541 ent->state_current.active = true;
542 if (bits & U_MODEL) ent->state_current.modelindex = (ent->state_current.modelindex & 0xFF00) | MSG_ReadByte();
543 if (bits & U_FRAME) ent->state_current.frame = (ent->state_current.frame & 0xFF00) | MSG_ReadByte();
544 if (bits & U_COLORMAP) ent->state_current.colormap = MSG_ReadByte();
545 if (bits & U_SKIN) ent->state_current.skin = MSG_ReadByte();
546 if (bits & U_EFFECTS) ent->state_current.effects = (ent->state_current.effects & 0xFF00) | MSG_ReadByte();
547 if (bits & U_ORIGIN1) ent->state_current.origin[0] = MSG_ReadCoord();
548 if (bits & U_ANGLE1) ent->state_current.angles[0] = MSG_ReadAngle();
549 if (bits & U_ORIGIN2) ent->state_current.origin[1] = MSG_ReadCoord();
550 if (bits & U_ANGLE2) ent->state_current.angles[1] = MSG_ReadAngle();
551 if (bits & U_ORIGIN3) ent->state_current.origin[2] = MSG_ReadCoord();
552 if (bits & U_ANGLE3) ent->state_current.angles[2] = MSG_ReadAngle();
553 if (bits & U_STEP) ent->state_current.flags |= RENDER_STEP;
554 if (bits & U_ALPHA) ent->state_current.alpha = MSG_ReadByte();
555 if (bits & U_SCALE) ent->state_current.scale = MSG_ReadByte();
556 if (bits & U_EFFECTS2) ent->state_current.effects = (ent->state_current.effects & 0x00FF) | (MSG_ReadByte() << 8);
557 if (bits & U_GLOWSIZE) ent->state_current.glowsize = MSG_ReadByte();
558 if (bits & U_GLOWCOLOR) ent->state_current.glowcolor = MSG_ReadByte();
559 if (bits & U_GLOWTRAIL) ent->state_current.flags |= RENDER_GLOWTRAIL;
560 if (bits & U_COLORMOD) ent->state_current.colormod = MSG_ReadByte();
561 if (bits & U_FRAME2) ent->state_current.frame = (ent->state_current.frame & 0x00FF) | (MSG_ReadByte() << 8);
562 if (bits & U_MODEL2) ent->state_current.modelindex = (ent->state_current.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
563 if (bits & U_VIEWMODEL) ent->state_current.flags |= RENDER_VIEWMODEL;
565 // LordHavoc: to allow playback of the Nehahra movie
566 if (Nehahrademcompatibility && (bits & U_EXTEND1))
568 // LordHavoc: evil format
569 int i = MSG_ReadFloat();
570 int j = MSG_ReadFloat() * 255.0f;
574 ent->state_current.effects |= EF_FULLBRIGHT;
577 ent->state_current.alpha = 0;
578 else if (j == 0 || j >= 255)
579 ent->state_current.alpha = 255;
581 ent->state_current.alpha = j;
587 ent->state_current.active = false;
591 CL_ValidateState(&ent->state_current);
594 if (!ent->state_current.active)
599 Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i %i\n", num, ent->state_previous.modelindex, ent->state_current.modelindex);
601 Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i\n", num, ent->state_previous.modelindex);
606 Con_Printf("CL_ParseUpdate: NULL model on %i: %i %i\n", num, ent->state_baseline.modelindex, ent->state_current.modelindex);
608 Con_Printf("CL_ParseUpdate: NULL model on %i: %i\n", num, ent->state_baseline.modelindex);
615 void CL_EntityUpdateSetup()
617 memset(entkill, 1, MAX_EDICTS);
620 int entityupdatestart;
621 void CL_EntityUpdateBegin(int start)
623 if (start < 0 || start >= MAX_EDICTS)
624 Host_Error("CL_EntityUpdateBegin: start (%i) < 0 or >= MAX_EDICTS (%i)\n", start, MAX_EDICTS);
625 entityupdatestart = start;
628 void CL_EntityUpdateEnd(int end)
631 if (end < 0 || end > MAX_EDICTS)
632 Host_Error("CL_EntityUpdateEnd: end (%i) < 0 or > MAX_EDICTS (%i)\n", end, MAX_EDICTS);
633 for (i = entityupdatestart;i < end;i++)
635 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
643 void CL_ParseBaseline (entity_t *ent, int largemodelindex)
647 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
648 ent->state_baseline.active = true;
650 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
652 ent->state_baseline.modelindex = MSG_ReadByte ();
653 ent->state_baseline.frame = MSG_ReadByte ();
654 ent->state_baseline.colormap = MSG_ReadByte();
655 ent->state_baseline.skin = MSG_ReadByte();
656 for (i = 0;i < 3;i++)
658 ent->state_baseline.origin[i] = MSG_ReadCoord ();
659 ent->state_baseline.angles[i] = MSG_ReadAngle ();
661 ent->state_baseline.alpha = 255;
662 ent->state_baseline.scale = 16;
663 ent->state_baseline.glowsize = 0;
664 ent->state_baseline.glowcolor = 254;
665 ent->state_baseline.colormod = 255;
666 ent->state_previous = ent->state_current = ent->state_baseline;
668 CL_ValidateState(&ent->state_baseline);
676 Server information pertaining to this client only
679 void CL_ParseClientdata (int bits)
684 if (bits & SU_EXTEND1)
685 bits |= (MSG_ReadByte() << 16);
686 if (bits & SU_EXTEND2)
687 bits |= (MSG_ReadByte() << 24);
689 if (bits & SU_VIEWHEIGHT)
690 cl.viewheight = MSG_ReadChar ();
692 cl.viewheight = DEFAULT_VIEWHEIGHT;
694 if (bits & SU_IDEALPITCH)
695 cl.idealpitch = MSG_ReadChar ();
699 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
700 for (i=0 ; i<3 ; i++)
702 if (bits & (SU_PUNCH1<<i) )
705 cl.punchangle[i] = MSG_ReadPreciseAngle();
707 cl.punchangle[i] = MSG_ReadChar();
710 cl.punchangle[i] = 0;
711 if (bits & (SU_PUNCHVEC1<<i))
712 cl.punchvector[i] = MSG_ReadFloatCoord();
714 cl.punchvector[i] = 0;
715 if (bits & (SU_VELOCITY1<<i) )
716 cl.mvelocity[0][i] = MSG_ReadChar()*16;
718 cl.mvelocity[0][i] = 0;
724 for (j=0 ; j<32 ; j++)
725 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
726 cl.item_gettime[j] = cl.time;
730 cl.onground = (bits & SU_ONGROUND) != 0;
731 cl.inwater = (bits & SU_INWATER) != 0;
733 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
734 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
735 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
736 cl.stats[STAT_HEALTH] = MSG_ReadShort();
737 cl.stats[STAT_AMMO] = MSG_ReadByte();
739 cl.stats[STAT_SHELLS] = MSG_ReadByte();
740 cl.stats[STAT_NAILS] = MSG_ReadByte();
741 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
742 cl.stats[STAT_CELLS] = MSG_ReadByte();
747 cl.stats[STAT_ACTIVEWEAPON] = i;
749 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
753 =====================
755 =====================
757 void CL_ParseStatic (int largemodelindex)
761 if (cl.num_statics >= MAX_STATIC_ENTITIES)
762 Host_Error ("Too many static entities");
763 ent = &cl_static_entities[cl.num_statics++];
764 CL_ParseBaseline (ent, largemodelindex);
766 // copy it to the current state
767 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
768 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
769 ent->render.framelerp = 0;
770 ent->render.lerp_starttime = -1;
771 // make torchs play out of sync
772 ent->render.frame1start = ent->render.frame2start = -(rand() & 32767);
773 ent->render.colormap = -1; // no special coloring
774 ent->render.skinnum = ent->state_baseline.skin;
775 ent->render.effects = ent->state_baseline.effects;
776 ent->render.alpha = 1;
777 ent->render.scale = 1;
778 ent->render.alpha = 1;
779 ent->render.glowsize = 0;
780 ent->render.glowcolor = 254;
781 ent->render.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
783 VectorCopy (ent->state_baseline.origin, ent->render.origin);
784 VectorCopy (ent->state_baseline.angles, ent->render.angles);
785 // R_AddEfrags (ent);
793 void CL_ParseStaticSound (void)
796 int sound_num, vol, atten;
799 sound_num = MSG_ReadByte ();
800 vol = MSG_ReadByte ();
801 atten = MSG_ReadByte ();
803 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
806 void CL_ParseEffect (void)
809 int modelindex, startframe, framecount, framerate;
812 modelindex = MSG_ReadByte ();
813 startframe = MSG_ReadByte ();
814 framecount = MSG_ReadByte ();
815 framerate = MSG_ReadByte ();
817 CL_Effect(org, modelindex, startframe, framecount, framerate);
820 void CL_ParseEffect2 (void)
823 int modelindex, startframe, framecount, framerate;
826 modelindex = MSG_ReadShort ();
827 startframe = MSG_ReadByte ();
828 framecount = MSG_ReadByte ();
829 framerate = MSG_ReadByte ();
831 CL_Effect(org, modelindex, startframe, framecount, framerate);
835 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
837 extern void SHOWLMP_decodehide();
838 extern void SHOWLMP_decodeshow();
839 extern void R_SetSkyBox(char* sky);
843 =====================
844 CL_ParseServerMessage
845 =====================
847 void CL_ParseServerMessage (void)
852 char *cmdlogname[32], *temp;
853 int cmdindex, cmdcount = 0;
856 // if recording demos, copy the message out
858 if (cl_shownet.value == 1)
860 Con_Printf ("%i ",net_message.cursize);
863 else if (cl_shownet.value == 2)
865 Con_Printf ("------------------\n");
869 cl.onground = false; // unless the server says otherwise
876 CL_EntityUpdateSetup();
881 Host_Error ("CL_ParseServerMessage: Bad server message");
883 cmd = MSG_ReadByte ();
887 SHOWNET("END OF MESSAGE");
888 break; // end of message
891 cmdindex = cmdcount & 31;
893 cmdlog[cmdindex] = cmd;
895 // if the high bit of the command byte is set, it is a fast update
898 // 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)
900 cmdlogname[cmdindex] = temp;
901 SHOWNET("fast update");
902 CL_ParseUpdate (cmd&127);
906 SHOWNET(svc_strings[cmd]);
907 cmdlogname[cmdindex] = svc_strings[cmd];
908 if (!cmdlogname[cmdindex])
910 // 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)
912 cmdlogname[cmdindex] = temp;
920 char description[32*64], temp[64];
922 strcpy(description, "packet dump: ");
926 count = cmdcount - i;
930 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
931 strcat(description, temp);
936 description[strlen(description)-1] = '\n'; // replace the last space with a newline
937 Con_Printf(description);
938 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
943 // Con_Printf ("svc_nop\n");
947 // handle old protocols which do not have entity update ranges
948 CL_EntityUpdateBegin(1);
950 cl.mtime[1] = cl.mtime[0];
951 cl.mtime[0] = MSG_ReadFloat ();
955 i = MSG_ReadShort ();
956 CL_ParseClientdata (i);
961 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
962 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
963 Nehahrademcompatibility = false;
965 Nehahrademcompatibility = true;
966 if (cls.demoplayback && demo_nehahra.value)
967 Nehahrademcompatibility = true;
968 dpprotocol = i == DPPROTOCOL_VERSION;
972 Host_EndGame ("Server disconnected\n");
975 Con_Printf ("%s", MSG_ReadString ());
978 case svc_centerprint:
979 SCR_CenterPrint (MSG_ReadString ());
983 Cbuf_AddText (MSG_ReadString ());
991 CL_ParseServerInfo ();
992 vid.recalc_refdef = true; // leave intermission full screen
996 for (i=0 ; i<3 ; i++)
997 cl.viewangles[i] = MSG_ReadAngle ();
1001 cl.viewentity = MSG_ReadShort ();
1004 case svc_lightstyle:
1005 i = MSG_ReadByte ();
1006 if (i >= MAX_LIGHTSTYLES)
1007 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1008 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1009 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1010 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1014 CL_ParseStartSoundPacket(false);
1018 CL_ParseStartSoundPacket(true);
1022 i = MSG_ReadShort();
1023 S_StopSound(i>>3, i&7);
1026 case svc_updatename:
1027 i = MSG_ReadByte ();
1028 if (i >= cl.maxclients)
1029 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1030 strcpy (cl.scores[i].name, MSG_ReadString ());
1033 case svc_updatefrags:
1034 i = MSG_ReadByte ();
1035 if (i >= cl.maxclients)
1036 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1037 cl.scores[i].frags = MSG_ReadShort ();
1040 case svc_updatecolors:
1041 i = MSG_ReadByte ();
1042 if (i >= cl.maxclients)
1043 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1044 cl.scores[i].colors = MSG_ReadByte ();
1048 R_ParseParticleEffect ();
1059 case svc_spawnbaseline:
1060 i = MSG_ReadShort ();
1061 // must use CL_EntityNum() to force cl.num_entities up
1062 CL_ParseBaseline (CL_EntityNum(i), false);
1064 case svc_spawnbaseline2:
1065 i = MSG_ReadShort ();
1066 // must use CL_EntityNum() to force cl.num_entities up
1067 CL_ParseBaseline (CL_EntityNum(i), false);
1069 case svc_spawnstatic:
1070 CL_ParseStatic (false);
1072 case svc_spawnstatic2:
1073 CL_ParseStatic (true);
1075 case svc_temp_entity:
1080 cl.paused = MSG_ReadByte ();
1088 i = MSG_ReadByte ();
1089 if (i <= cls.signon)
1090 Host_Error ("Received signon %i when at %i", i, cls.signon);
1095 case svc_killedmonster:
1096 cl.stats[STAT_MONSTERS]++;
1099 case svc_foundsecret:
1100 cl.stats[STAT_SECRETS]++;
1103 case svc_updatestat:
1104 i = MSG_ReadByte ();
1105 if (i < 0 || i >= MAX_CL_STATS)
1106 Host_Error ("svc_updatestat: %i is invalid", i);
1107 cl.stats[i] = MSG_ReadLong ();
1110 case svc_spawnstaticsound:
1111 CL_ParseStaticSound ();
1115 cl.cdtrack = MSG_ReadByte ();
1116 cl.looptrack = MSG_ReadByte ();
1117 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1118 CDAudio_Play ((byte)cls.forcetrack, true);
1120 CDAudio_Play ((byte)cl.cdtrack, true);
1123 case svc_intermission:
1124 cl.intermission = 1;
1125 cl.completed_time = cl.time;
1126 vid.recalc_refdef = true; // go to full screen
1130 cl.intermission = 2;
1131 cl.completed_time = cl.time;
1132 vid.recalc_refdef = true; // go to full screen
1133 SCR_CenterPrint (MSG_ReadString ());
1137 cl.intermission = 3;
1138 cl.completed_time = cl.time;
1139 vid.recalc_refdef = true; // go to full screen
1140 SCR_CenterPrint (MSG_ReadString ());
1143 case svc_sellscreen:
1144 Cmd_ExecuteString ("help", src_command);
1147 SHOWLMP_decodehide();
1150 SHOWLMP_decodeshow();
1152 case svc_entitiesbegin:
1153 // the beginning of an entity update range
1154 CL_EntityUpdateBegin((unsigned) MSG_ReadShort());
1156 case svc_entitiesend:
1157 // the end of an entity update range
1158 CL_EntityUpdateEnd((unsigned) MSG_ReadShort());
1165 CL_EntityUpdateEnd(MAX_EDICTS);