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
83 "svc_cgame", // 50 // [short] length [bytes] data
84 "svc_unusedlh1", // 51 // unused
85 "svc_effect", // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
86 "svc_effect2", // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
87 "svc_sound2", // 54 // short soundindex instead of byte
88 "svc_spawnbaseline2", // 55 // short modelindex instead of byte
89 "svc_spawnstatic2", // 56 // short modelindex instead of byte
90 "svc_entities", // 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata
91 "svc_unusedlh3", // 58
92 "svc_spawnstaticsound2", // 59 // [coord3] [short] samp [byte] vol [byte] aten
95 //=============================================================================
97 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
99 void CL_Parse_Init(void)
101 // LordHavoc: added demo_nehahra cvar
102 Cvar_RegisterVariable (&demo_nehahra);
103 if (gamemode == GAME_NEHAHRA)
104 Cvar_SetValue("demo_nehahra", 1);
107 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
108 int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces
112 CL_ParseStartSoundPacket
115 void CL_ParseStartSoundPacket(int largesoundindex)
125 field_mask = MSG_ReadByte();
127 if (field_mask & SND_VOLUME)
128 volume = MSG_ReadByte ();
130 volume = DEFAULT_SOUND_PACKET_VOLUME;
132 if (field_mask & SND_ATTENUATION)
133 attenuation = MSG_ReadByte () / 64.0;
135 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
137 channel = MSG_ReadShort ();
139 sound_num = (unsigned short) MSG_ReadShort ();
141 sound_num = MSG_ReadByte ();
143 if (sound_num >= MAX_SOUNDS)
144 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
149 if (ent > MAX_EDICTS)
150 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
152 for (i=0 ; i<3 ; i++)
153 pos[i] = MSG_ReadCoord ();
155 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
162 When the client is taking a long time to load stuff, send keepalive messages
163 so the server doesn't disconnect.
166 void CL_KeepaliveMessage (void)
169 static float lastmsg;
176 return; // no need if server is local
177 if (cls.demoplayback)
180 // read messages from server, should just be nops
182 memcpy (olddata, net_message.data, net_message.cursize);
186 ret = CL_GetMessage ();
190 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
192 break; // nothing waiting
194 Host_Error ("CL_KeepaliveMessage: received a message");
199 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
205 memcpy (net_message.data, olddata, net_message.cursize);
208 time = Sys_DoubleTime ();
209 if (time - lastmsg < 5)
214 Con_Printf ("--> client to server keepalive\n");
216 MSG_WriteByte (&cls.message, clc_nop);
217 NET_SendMessage (cls.netcon, &cls.message);
218 SZ_Clear (&cls.message);
221 void CL_ParseEntityLump(char *entdata)
224 char key[128], value[4096];
225 FOG_clear(); // LordHavoc: no fog until set
226 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
230 data = COM_Parse(data);
233 if (com_token[0] != '{')
237 data = COM_Parse(data);
240 if (com_token[0] == '}')
241 break; // end of worldspawn
242 if (com_token[0] == '_')
243 strcpy(key, com_token + 1);
245 strcpy(key, com_token);
246 while (key[strlen(key)-1] == ' ') // remove trailing spaces
247 key[strlen(key)-1] = 0;
248 data = COM_Parse(data);
251 strcpy(value, com_token);
252 if (!strcmp("sky", key))
254 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
256 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
258 else if (!strcmp("fog", key))
259 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
260 else if (!strcmp("fog_density", key))
261 fog_density = atof(value);
262 else if (!strcmp("fog_red", key))
263 fog_red = atof(value);
264 else if (!strcmp("fog_green", key))
265 fog_green = atof(value);
266 else if (!strcmp("fog_blue", key))
267 fog_blue = atof(value);
272 =====================
275 An svc_signonnum has been received, perform a client side setup
276 =====================
278 static void CL_SignonReply (void)
282 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
287 MSG_WriteByte (&cls.message, clc_stringcmd);
288 MSG_WriteString (&cls.message, "prespawn");
292 MSG_WriteByte (&cls.message, clc_stringcmd);
293 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
295 MSG_WriteByte (&cls.message, clc_stringcmd);
296 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
298 if (cl_pmodel.integer)
300 MSG_WriteByte (&cls.message, clc_stringcmd);
301 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
304 MSG_WriteByte (&cls.message, clc_stringcmd);
305 //sprintf (str, "spawn %s", cls.spawnparms);
306 //MSG_WriteString (&cls.message, str);
307 MSG_WriteString (&cls.message, "spawn");
311 MSG_WriteByte (&cls.message, clc_stringcmd);
312 MSG_WriteString (&cls.message, "begin");
326 qbyte entlife[MAX_EDICTS];
327 void CL_ParseServerInfo (void)
331 int nummodels, numsounds;
332 char model_precache[MAX_MODELS][MAX_QPATH];
333 char sound_precache[MAX_SOUNDS][MAX_QPATH];
336 Con_DPrintf ("Serverinfo packet received.\n");
338 // wipe the client_state_t struct
342 // parse protocol version number
344 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
346 Con_Printf ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
349 Nehahrademcompatibility = false;
351 Nehahrademcompatibility = true;
352 if (cls.demoplayback && demo_nehahra.integer)
353 Nehahrademcompatibility = true;
355 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
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 = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.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
387 Mem_CheckSentinelsGlobal();
391 // disable until we get textures for it
395 memset (cl.model_precache, 0, sizeof(cl.model_precache));
396 for (nummodels=1 ; ; nummodels++)
398 str = MSG_ReadString ();
401 if (nummodels==MAX_MODELS)
403 Host_Error ("Server sent too many model precaches\n");
406 if (strlen(str) >= MAX_QPATH)
407 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
408 strcpy (model_precache[nummodels], str);
409 Mod_TouchModel (str);
413 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
414 for (numsounds=1 ; ; numsounds++)
416 str = MSG_ReadString ();
419 if (numsounds==MAX_SOUNDS)
421 Host_Error ("Server sent too many sound precaches\n");
424 if (strlen(str) >= MAX_QPATH)
425 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
426 strcpy (sound_precache[numsounds], str);
433 // now we try to load everything else until a cache allocation fails
436 for (i=1 ; i<nummodels ; i++)
438 // LordHavoc: i == 1 means the first model is the world model
439 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
440 if (cl.model_precache[i] == NULL)
442 Con_Printf("Model %s not found\n", model_precache[i]);
445 CL_KeepaliveMessage ();
448 S_BeginPrecaching ();
449 for (i=1 ; i<numsounds ; i++)
451 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
452 CL_KeepaliveMessage ();
457 ent = &cl_entities[0];
458 // entire entity array was cleared, so just fill in a few fields
459 ent->state_current.active = true;
460 ent->render.model = cl.worldmodel = cl.model_precache[1];
461 ent->render.scale = 1;
462 ent->render.alpha = 1;
463 CL_BoundingBoxForEntity(&ent->render);
464 // clear entlife array
465 memset(entlife, 0, MAX_EDICTS);
472 noclip_anglehack = false; // noclip is turned off at start
474 Mem_CheckSentinelsGlobal();
478 void CL_ValidateState(entity_state_t *s)
485 if (s->modelindex >= MAX_MODELS)
486 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
488 // colormap is client index + 1
489 if (s->colormap > cl.maxclients)
490 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
492 model = cl.model_precache[s->modelindex];
493 Mod_CheckLoaded(model);
494 if (model && s->frame >= model->numframes)
496 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
499 if (model && s->skin > 0 && s->skin >= model->numskins)
501 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
506 void CL_MoveLerpEntityStates(entity_t *ent)
508 float odelta[3], adelta[3];
509 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
510 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
511 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
513 // we definitely shouldn't lerp
514 ent->persistent.lerpdeltatime = 0;
515 ent->persistent.lerpstarttime = cl.mtime[1];
516 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
517 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
518 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
519 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
521 else// if (ent->state_current.flags & RENDER_STEP)
523 // monster interpolation
524 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
526 ent->persistent.lerpdeltatime = cl.time - ent->persistent.lerpstarttime;
527 ent->persistent.lerpstarttime = cl.mtime[1];
528 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
529 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
530 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
531 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
538 ent->persistent.lerpstarttime = cl.mtime[1];
539 // no lerp if it's singleplayer
540 //if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
541 // ent->persistent.lerpdeltatime = 0;
543 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
544 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
545 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
546 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
547 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
556 Parse an entity update message from the server
557 If an entities model or origin changes from frame to frame, it must be
558 relinked. Other attributes can change without relinking.
561 int bitprofile[32], bitprofilecount = 0;
562 void CL_ParseUpdate (int bits)
568 if (bits & U_MOREBITS)
569 bits |= (MSG_ReadByte()<<8);
570 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
572 bits |= MSG_ReadByte() << 16;
573 if (bits & U_EXTEND2)
574 bits |= MSG_ReadByte() << 24;
577 if (bits & U_LONGENTITY)
578 num = (unsigned) MSG_ReadShort ();
580 num = (unsigned) MSG_ReadByte ();
582 if (num >= MAX_EDICTS)
583 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
585 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
587 ent = cl_entities + num;
589 for (i = 0;i < 32;i++)
594 // note: this inherits the 'active' state of the baseline chosen
595 // (state_baseline is always active, state_current may not be active if
596 // the entity was missing in the last frame)
598 new = ent->state_current;
601 new = ent->state_baseline;
606 new.time = cl.mtime[0];
608 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
609 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
610 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
611 if (bits & U_SKIN) new.skin = MSG_ReadByte();
612 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
613 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
614 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
615 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
616 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
617 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
618 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
619 if (bits & U_STEP) new.flags |= RENDER_STEP;
620 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
621 if (bits & U_SCALE) new.scale = MSG_ReadByte();
622 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
623 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
624 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
625 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
626 if (bits & U_COLORMOD) MSG_ReadByte();
627 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
628 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
629 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
630 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
631 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
633 // LordHavoc: to allow playback of the Nehahra movie
634 if (Nehahrademcompatibility && (bits & U_EXTEND1))
636 // LordHavoc: evil format
637 int i = MSG_ReadFloat();
638 int j = MSG_ReadFloat() * 255.0f;
643 new.effects |= EF_FULLBRIGHT;
647 else if (j == 0 || j >= 255)
654 CL_ValidateState(&new);
656 ent->state_previous = ent->state_current;
657 ent->state_current = new;
658 if (ent->state_current.active)
660 CL_MoveLerpEntityStates(ent);
661 cl_entities_active[ent->state_current.number] = true;
662 // mark as visible (no kill this frame)
663 entlife[ent->state_current.number] = 2;
667 void CL_ReadEntityFrame(void)
670 entity_frame_t entityframe;
672 EntityFrame_Read(&cl.entitydatabase);
673 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
674 for (i = 0;i < entityframe.numentities;i++)
677 ent = &cl_entities[entityframe.entitydata[i].number];
678 ent->state_previous = ent->state_current;
679 ent->state_current = entityframe.entitydata[i];
680 CL_MoveLerpEntityStates(ent);
681 // the entity lives again...
682 entlife[ent->state_current.number] = 2;
683 cl_entities_active[ent->state_current.number] = true;
685 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
686 VectorCopy(entityframe.eye, cl.viewentoriginnew);
689 char *bitprofilenames[32] =
713 "obsolete U_COLORMOD",
725 void CL_BitProfile_f(void)
728 Con_Printf("bitprofile: %i updates\n");
730 for (i = 0;i < 32;i++)
731 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
733 for (i = 0;i < 32;i++)
738 void CL_EntityUpdateSetup(void)
742 void CL_EntityUpdateEnd(void)
745 // disable entities that disappeared this frame
746 for (i = 1;i < MAX_EDICTS;i++)
748 // clear only the entities that were active last frame but not this
749 // frame, don't waste time clearing all entities (which would cause
755 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
765 void CL_ParseBaseline (entity_t *ent, int large)
769 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
770 ent->state_baseline.active = true;
773 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
774 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
778 ent->state_baseline.modelindex = MSG_ReadByte ();
779 ent->state_baseline.frame = MSG_ReadByte ();
781 ent->state_baseline.colormap = MSG_ReadByte();
782 ent->state_baseline.skin = MSG_ReadByte();
783 for (i = 0;i < 3;i++)
785 ent->state_baseline.origin[i] = MSG_ReadCoord ();
786 ent->state_baseline.angles[i] = MSG_ReadAngle ();
788 ent->state_baseline.alpha = 255;
789 ent->state_baseline.scale = 16;
790 ent->state_baseline.glowsize = 0;
791 ent->state_baseline.glowcolor = 254;
792 ent->state_previous = ent->state_current = ent->state_baseline;
794 CL_ValidateState(&ent->state_baseline);
802 Server information pertaining to this client only
805 void CL_ParseClientdata (int bits)
810 if (bits & SU_EXTEND1)
811 bits |= (MSG_ReadByte() << 16);
812 if (bits & SU_EXTEND2)
813 bits |= (MSG_ReadByte() << 24);
815 if (bits & SU_VIEWHEIGHT)
816 cl.viewheight = MSG_ReadChar ();
818 cl.viewheight = DEFAULT_VIEWHEIGHT;
820 if (bits & SU_IDEALPITCH)
821 cl.idealpitch = MSG_ReadChar ();
825 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
826 for (i=0 ; i<3 ; i++)
828 if (bits & (SU_PUNCH1<<i) )
831 cl.punchangle[i] = MSG_ReadPreciseAngle();
833 cl.punchangle[i] = MSG_ReadChar();
836 cl.punchangle[i] = 0;
837 if (bits & (SU_PUNCHVEC1<<i))
838 cl.punchvector[i] = MSG_ReadCoord();
840 cl.punchvector[i] = 0;
841 if (bits & (SU_VELOCITY1<<i) )
842 cl.mvelocity[0][i] = MSG_ReadChar()*16;
844 cl.mvelocity[0][i] = 0;
850 for (j=0 ; j<32 ; j++)
851 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
852 cl.item_gettime[j] = cl.time;
856 cl.onground = (bits & SU_ONGROUND) != 0;
857 cl.inwater = (bits & SU_INWATER) != 0;
859 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
860 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
861 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
862 cl.stats[STAT_HEALTH] = MSG_ReadShort();
863 cl.stats[STAT_AMMO] = MSG_ReadByte();
865 cl.stats[STAT_SHELLS] = MSG_ReadByte();
866 cl.stats[STAT_NAILS] = MSG_ReadByte();
867 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
868 cl.stats[STAT_CELLS] = MSG_ReadByte();
872 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
873 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
875 cl.stats[STAT_ACTIVEWEAPON] = i;
877 cl.viewzoomold = cl.viewzoomnew; // for interpolation
878 if (bits & SU_VIEWZOOM)
883 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
891 =====================
893 =====================
895 void CL_ParseStatic (int large)
899 if (cl_num_static_entities >= cl_max_static_entities)
900 Host_Error ("Too many static entities");
901 ent = &cl_static_entities[cl_num_static_entities++];
902 CL_ParseBaseline (ent, large);
904 // copy it to the current state
905 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
906 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
907 ent->render.framelerp = 0;
908 // make torchs play out of sync
909 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
910 ent->render.colormap = -1; // no special coloring
911 ent->render.skinnum = ent->state_baseline.skin;
912 ent->render.effects = ent->state_baseline.effects;
913 ent->render.alpha = 1;
914 ent->render.scale = 1;
915 ent->render.alpha = 1;
917 VectorCopy (ent->state_baseline.origin, ent->render.origin);
918 VectorCopy (ent->state_baseline.angles, ent->render.angles);
920 CL_BoundingBoxForEntity(&ent->render);
922 // This is definitely cheating...
923 if (ent->render.model == NULL)
924 cl_num_static_entities--;
932 void CL_ParseStaticSound (int large)
935 int sound_num, vol, atten;
939 sound_num = (unsigned short) MSG_ReadShort ();
941 sound_num = MSG_ReadByte ();
942 vol = MSG_ReadByte ();
943 atten = MSG_ReadByte ();
945 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
948 void CL_ParseEffect (void)
951 int modelindex, startframe, framecount, framerate;
954 modelindex = MSG_ReadByte ();
955 startframe = MSG_ReadByte ();
956 framecount = MSG_ReadByte ();
957 framerate = MSG_ReadByte ();
959 CL_Effect(org, modelindex, startframe, framecount, framerate);
962 void CL_ParseEffect2 (void)
965 int modelindex, startframe, framecount, framerate;
968 modelindex = MSG_ReadShort ();
969 startframe = MSG_ReadShort ();
970 framecount = MSG_ReadByte ();
971 framerate = MSG_ReadByte ();
973 CL_Effect(org, modelindex, startframe, framecount, framerate);
977 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
979 static qbyte cgamenetbuffer[65536];
982 =====================
983 CL_ParseServerMessage
984 =====================
986 void CL_ParseServerMessage (void)
989 int i, entitiesupdated;
991 char *cmdlogname[32], *temp;
992 int cmdindex, cmdcount = 0;
995 // if recording demos, copy the message out
997 if (cl_shownet.integer == 1)
998 Con_Printf ("%i ",net_message.cursize);
999 else if (cl_shownet.integer == 2)
1000 Con_Printf ("------------------\n");
1002 cl.onground = false; // unless the server says otherwise
1004 // parse the message
1006 MSG_BeginReading ();
1008 entitiesupdated = false;
1013 Host_Error ("CL_ParseServerMessage: Bad server message");
1015 cmd = MSG_ReadByte ();
1019 SHOWNET("END OF MESSAGE");
1020 break; // end of message
1023 cmdindex = cmdcount & 31;
1025 cmdlog[cmdindex] = cmd;
1027 // if the high bit of the command byte is set, it is a fast update
1030 // 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)
1032 cmdlogname[cmdindex] = temp;
1033 SHOWNET("fast update");
1034 if (cls.signon == SIGNONS - 1)
1036 // first update is the final signon stage
1037 cls.signon = SIGNONS;
1040 CL_ParseUpdate (cmd&127);
1044 SHOWNET(svc_strings[cmd]);
1045 cmdlogname[cmdindex] = svc_strings[cmd];
1046 if (!cmdlogname[cmdindex])
1048 // 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)
1050 cmdlogname[cmdindex] = temp;
1058 char description[32*64], temp[64];
1060 strcpy(description, "packet dump: ");
1064 count = cmdcount - i;
1068 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1069 strcat(description, temp);
1074 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1075 Con_Printf("%s", description);
1076 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1084 if (!entitiesupdated)
1086 // this is a new frame, we'll be seeing entities,
1087 // so prepare for entity updates
1088 CL_EntityUpdateSetup();
1089 entitiesupdated = true;
1091 cl.mtime[1] = cl.mtime[0];
1092 cl.mtime[0] = MSG_ReadFloat ();
1095 case svc_clientdata:
1096 i = MSG_ReadShort ();
1097 CL_ParseClientdata (i);
1101 i = MSG_ReadLong ();
1102 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1103 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1104 Nehahrademcompatibility = false;
1106 Nehahrademcompatibility = true;
1107 if (cls.demoplayback && demo_nehahra.integer)
1108 Nehahrademcompatibility = true;
1110 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1114 case svc_disconnect:
1115 Host_EndGame ("Server disconnected\n");
1118 Con_Printf ("%s", MSG_ReadString ());
1121 case svc_centerprint:
1122 SCR_CenterPrint (MSG_ReadString ());
1126 Cbuf_AddText (MSG_ReadString ());
1133 case svc_serverinfo:
1134 CL_ParseServerInfo ();
1138 for (i=0 ; i<3 ; i++)
1139 cl.viewangles[i] = MSG_ReadAngle ();
1143 cl.viewentity = MSG_ReadShort ();
1144 // LordHavoc: assume first setview recieved is the real player entity
1145 if (!cl.playerentity)
1146 cl.playerentity = cl.viewentity;
1149 case svc_lightstyle:
1150 i = MSG_ReadByte ();
1151 if (i >= MAX_LIGHTSTYLES)
1152 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1153 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1154 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1155 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1159 CL_ParseStartSoundPacket(false);
1163 CL_ParseStartSoundPacket(true);
1167 i = MSG_ReadShort();
1168 S_StopSound(i>>3, i&7);
1171 case svc_updatename:
1172 i = MSG_ReadByte ();
1173 if (i >= cl.maxclients)
1174 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1175 strcpy (cl.scores[i].name, MSG_ReadString ());
1178 case svc_updatefrags:
1179 i = MSG_ReadByte ();
1180 if (i >= cl.maxclients)
1181 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1182 cl.scores[i].frags = MSG_ReadShort ();
1185 case svc_updatecolors:
1186 i = MSG_ReadByte ();
1187 if (i >= cl.maxclients)
1188 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1189 cl.scores[i].colors = MSG_ReadByte ();
1190 // update our color cvar if our color changed
1191 if (i == cl.playerentity - 1)
1192 Cvar_SetValue ("_cl_color", cl.scores[i].colors);
1196 CL_ParseParticleEffect ();
1207 case svc_spawnbaseline:
1208 i = MSG_ReadShort ();
1209 if (i < 0 || i >= MAX_EDICTS)
1210 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1211 CL_ParseBaseline (cl_entities + i, false);
1213 case svc_spawnbaseline2:
1214 i = MSG_ReadShort ();
1215 if (i < 0 || i >= MAX_EDICTS)
1216 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1217 CL_ParseBaseline (cl_entities + i, true);
1219 case svc_spawnstatic:
1220 CL_ParseStatic (false);
1222 case svc_spawnstatic2:
1223 CL_ParseStatic (true);
1225 case svc_temp_entity:
1230 cl.paused = MSG_ReadByte ();
1238 i = MSG_ReadByte ();
1239 if (i <= cls.signon)
1240 Host_Error ("Received signon %i when at %i", i, cls.signon);
1245 case svc_killedmonster:
1246 cl.stats[STAT_MONSTERS]++;
1249 case svc_foundsecret:
1250 cl.stats[STAT_SECRETS]++;
1253 case svc_updatestat:
1254 i = MSG_ReadByte ();
1255 if (i < 0 || i >= MAX_CL_STATS)
1256 Host_Error ("svc_updatestat: %i is invalid", i);
1257 cl.stats[i] = MSG_ReadLong ();
1260 case svc_spawnstaticsound:
1261 CL_ParseStaticSound (false);
1264 case svc_spawnstaticsound2:
1265 CL_ParseStaticSound (true);
1269 cl.cdtrack = MSG_ReadByte ();
1270 cl.looptrack = MSG_ReadByte ();
1271 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1272 CDAudio_Play ((qbyte)cls.forcetrack, true);
1274 CDAudio_Play ((qbyte)cl.cdtrack, true);
1277 case svc_intermission:
1278 cl.intermission = 1;
1279 cl.completed_time = cl.time;
1283 cl.intermission = 2;
1284 cl.completed_time = cl.time;
1285 SCR_CenterPrint (MSG_ReadString ());
1289 cl.intermission = 3;
1290 cl.completed_time = cl.time;
1291 SCR_CenterPrint (MSG_ReadString ());
1294 case svc_sellscreen:
1295 Cmd_ExecuteString ("help", src_command);
1298 SHOWLMP_decodehide();
1301 SHOWLMP_decodeshow();
1304 R_SetSkyBox(MSG_ReadString());
1309 length = (int) ((unsigned short) MSG_ReadShort());
1310 for (i = 0;i < length;i++)
1311 cgamenetbuffer[i] = MSG_ReadByte();
1313 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1317 if (cls.signon == SIGNONS - 1)
1319 // first update is the final signon stage
1320 cls.signon = SIGNONS;
1323 CL_ReadEntityFrame();
1328 if (entitiesupdated)
1329 CL_EntityUpdateEnd();