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();
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 Host_Error ("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 Host_Error ("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);
430 // now we try to load everything else until a cache allocation fails
433 for (i=1 ; i<nummodels ; i++)
435 // LordHavoc: i == 1 means the first model is the world model
436 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
438 if (cl.model_precache[i] == NULL)
440 Host_Error("Model %s not found\n", model_precache[i]);
443 CL_KeepaliveMessage ();
446 S_BeginPrecaching ();
447 for (i=1 ; i<numsounds ; i++)
449 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
450 CL_KeepaliveMessage ();
455 ent = &cl_entities[0];
456 // entire entity array was cleared, so just fill in a few fields
457 ent->state_current.active = true;
458 ent->render.model = cl.worldmodel = cl.model_precache[1];
459 ent->render.scale = 1;
460 ent->render.alpha = 1;
461 VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins);
462 VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs);
463 // clear entlife array
464 memset(entlife, 0, MAX_EDICTS);
472 Mem_CheckSentinelsGlobal();
474 noclip_anglehack = false; // noclip is turned off at start
477 void CL_ValidateState(entity_state_t *s)
484 if (s->modelindex >= MAX_MODELS)
485 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
487 // colormap is client index + 1
488 if (s->colormap > cl.maxclients)
489 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
491 model = cl.model_precache[s->modelindex];
492 Mod_CheckLoaded(model);
493 if (model && s->frame >= model->numframes)
495 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
498 if (model && s->skin > 0 && s->skin >= model->numskins)
500 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
505 void CL_MoveLerpEntityStates(entity_t *ent)
507 float odelta[3], adelta[3];
508 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
509 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
510 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
512 // we definitely shouldn't lerp
513 ent->persistent.lerpdeltatime = 0;
514 ent->persistent.lerpstarttime = cl.mtime[1];
515 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
516 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
517 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
518 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
520 else// if (ent->state_current.flags & RENDER_STEP)
522 // monster interpolation
523 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
525 ent->persistent.lerpdeltatime = cl.time - ent->persistent.lerpstarttime;
526 ent->persistent.lerpstarttime = cl.mtime[1];
527 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
528 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
529 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
530 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
537 ent->persistent.lerpstarttime = cl.mtime[1];
538 // no lerp if it's singleplayer
539 //if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
540 // ent->persistent.lerpdeltatime = 0;
542 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
543 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
544 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
545 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
546 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
555 Parse an entity update message from the server
556 If an entities model or origin changes from frame to frame, it must be
557 relinked. Other attributes can change without relinking.
560 int bitprofile[32], bitprofilecount = 0;
561 void CL_ParseUpdate (int bits)
567 if (bits & U_MOREBITS)
568 bits |= (MSG_ReadByte()<<8);
569 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
571 bits |= MSG_ReadByte() << 16;
572 if (bits & U_EXTEND2)
573 bits |= MSG_ReadByte() << 24;
576 if (bits & U_LONGENTITY)
577 num = (unsigned) MSG_ReadShort ();
579 num = (unsigned) MSG_ReadByte ();
581 if (num >= MAX_EDICTS)
582 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
584 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
586 ent = cl_entities + num;
588 for (i = 0;i < 32;i++)
593 // note: this inherits the 'active' state of the baseline chosen
594 // (state_baseline is always active, state_current may not be active if
595 // the entity was missing in the last frame)
597 new = ent->state_current;
600 new = ent->state_baseline;
605 new.time = cl.mtime[0];
607 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
608 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
609 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
610 if (bits & U_SKIN) new.skin = MSG_ReadByte();
611 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
612 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
613 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
614 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
615 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
616 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
617 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
618 if (bits & U_STEP) new.flags |= RENDER_STEP;
619 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
620 if (bits & U_SCALE) new.scale = MSG_ReadByte();
621 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
622 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
623 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
624 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
625 if (bits & U_COLORMOD) MSG_ReadByte();
626 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
627 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
628 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
629 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
630 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
632 // LordHavoc: to allow playback of the Nehahra movie
633 if (Nehahrademcompatibility && (bits & U_EXTEND1))
635 // LordHavoc: evil format
636 int i = MSG_ReadFloat();
637 int j = MSG_ReadFloat() * 255.0f;
642 new.effects |= EF_FULLBRIGHT;
646 else if (j == 0 || j >= 255)
653 CL_ValidateState(&new);
655 ent->state_previous = ent->state_current;
656 ent->state_current = new;
657 if (ent->state_current.active)
659 CL_MoveLerpEntityStates(ent);
660 cl_entities_active[ent->state_current.number] = true;
661 // mark as visible (no kill this frame)
662 entlife[ent->state_current.number] = 2;
666 void CL_ReadEntityFrame(void)
669 entity_frame_t entityframe;
671 EntityFrame_Read(&cl.entitydatabase);
672 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
673 for (i = 0;i < entityframe.numentities;i++)
676 ent = &cl_entities[entityframe.entitydata[i].number];
677 ent->state_previous = ent->state_current;
678 ent->state_current = entityframe.entitydata[i];
679 CL_MoveLerpEntityStates(ent);
680 // the entity lives again...
681 entlife[ent->state_current.number] = 2;
682 cl_entities_active[ent->state_current.number] = true;
684 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
685 VectorCopy(entityframe.eye, cl.viewentoriginnew);
688 char *bitprofilenames[32] =
712 "obsolete U_COLORMOD",
724 void CL_BitProfile_f(void)
727 Con_Printf("bitprofile: %i updates\n");
729 for (i = 0;i < 32;i++)
730 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
732 for (i = 0;i < 32;i++)
737 void CL_EntityUpdateSetup(void)
741 void CL_EntityUpdateEnd(void)
744 // disable entities that disappeared this frame
745 for (i = 1;i < MAX_EDICTS;i++)
747 // clear only the entities that were active last frame but not this
748 // frame, don't waste time clearing all entities (which would cause
754 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
764 void CL_ParseBaseline (entity_t *ent, int large)
768 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
769 ent->state_baseline.active = true;
772 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
773 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
777 ent->state_baseline.modelindex = MSG_ReadByte ();
778 ent->state_baseline.frame = MSG_ReadByte ();
780 ent->state_baseline.colormap = MSG_ReadByte();
781 ent->state_baseline.skin = MSG_ReadByte();
782 for (i = 0;i < 3;i++)
784 ent->state_baseline.origin[i] = MSG_ReadCoord ();
785 ent->state_baseline.angles[i] = MSG_ReadAngle ();
787 ent->state_baseline.alpha = 255;
788 ent->state_baseline.scale = 16;
789 ent->state_baseline.glowsize = 0;
790 ent->state_baseline.glowcolor = 254;
791 ent->state_previous = ent->state_current = ent->state_baseline;
793 CL_ValidateState(&ent->state_baseline);
801 Server information pertaining to this client only
804 void CL_ParseClientdata (int bits)
809 if (bits & SU_EXTEND1)
810 bits |= (MSG_ReadByte() << 16);
811 if (bits & SU_EXTEND2)
812 bits |= (MSG_ReadByte() << 24);
814 if (bits & SU_VIEWHEIGHT)
815 cl.viewheight = MSG_ReadChar ();
817 cl.viewheight = DEFAULT_VIEWHEIGHT;
819 if (bits & SU_IDEALPITCH)
820 cl.idealpitch = MSG_ReadChar ();
824 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
825 for (i=0 ; i<3 ; i++)
827 if (bits & (SU_PUNCH1<<i) )
830 cl.punchangle[i] = MSG_ReadPreciseAngle();
832 cl.punchangle[i] = MSG_ReadChar();
835 cl.punchangle[i] = 0;
836 if (bits & (SU_PUNCHVEC1<<i))
837 cl.punchvector[i] = MSG_ReadCoord();
839 cl.punchvector[i] = 0;
840 if (bits & (SU_VELOCITY1<<i) )
841 cl.mvelocity[0][i] = MSG_ReadChar()*16;
843 cl.mvelocity[0][i] = 0;
849 for (j=0 ; j<32 ; j++)
850 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
851 cl.item_gettime[j] = cl.time;
855 cl.onground = (bits & SU_ONGROUND) != 0;
856 cl.inwater = (bits & SU_INWATER) != 0;
858 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
859 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
860 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
861 cl.stats[STAT_HEALTH] = MSG_ReadShort();
862 cl.stats[STAT_AMMO] = MSG_ReadByte();
864 cl.stats[STAT_SHELLS] = MSG_ReadByte();
865 cl.stats[STAT_NAILS] = MSG_ReadByte();
866 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
867 cl.stats[STAT_CELLS] = MSG_ReadByte();
871 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
872 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
874 cl.stats[STAT_ACTIVEWEAPON] = i;
876 cl.viewzoomold = cl.viewzoomnew; // for interpolation
877 if (bits & SU_VIEWZOOM)
882 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
890 =====================
892 =====================
894 void CL_ParseStatic (int large)
898 if (cl_num_static_entities >= cl_max_static_entities)
899 Host_Error ("Too many static entities");
900 ent = &cl_static_entities[cl_num_static_entities++];
901 CL_ParseBaseline (ent, large);
903 // copy it to the current state
904 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
905 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
906 ent->render.framelerp = 0;
907 // make torchs play out of sync
908 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
909 ent->render.colormap = -1; // no special coloring
910 ent->render.skinnum = ent->state_baseline.skin;
911 ent->render.effects = ent->state_baseline.effects;
912 ent->render.alpha = 1;
913 ent->render.scale = 1;
914 ent->render.alpha = 1;
916 VectorCopy (ent->state_baseline.origin, ent->render.origin);
917 VectorCopy (ent->state_baseline.angles, ent->render.angles);
919 if (ent->render.angles[0] || ent->render.angles[2])
922 VectorAdd(ent->render.origin, ent->render.model->rotatedmins, ent->render.mins);
923 VectorAdd(ent->render.origin, ent->render.model->rotatedmaxs, ent->render.maxs);
925 else if (ent->render.angles[1])
928 VectorAdd(ent->render.origin, ent->render.model->yawmins, ent->render.mins);
929 VectorAdd(ent->render.origin, ent->render.model->yawmaxs, ent->render.maxs);
933 VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins);
934 VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs);
937 // This is definitely cheating...
938 if (ent->render.model == NULL)
939 cl_num_static_entities--;
947 void CL_ParseStaticSound (int large)
950 int sound_num, vol, atten;
954 sound_num = (unsigned short) MSG_ReadShort ();
956 sound_num = MSG_ReadByte ();
957 vol = MSG_ReadByte ();
958 atten = MSG_ReadByte ();
960 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
963 void CL_ParseEffect (void)
966 int modelindex, startframe, framecount, framerate;
969 modelindex = MSG_ReadByte ();
970 startframe = MSG_ReadByte ();
971 framecount = MSG_ReadByte ();
972 framerate = MSG_ReadByte ();
974 CL_Effect(org, modelindex, startframe, framecount, framerate);
977 void CL_ParseEffect2 (void)
980 int modelindex, startframe, framecount, framerate;
983 modelindex = MSG_ReadShort ();
984 startframe = MSG_ReadShort ();
985 framecount = MSG_ReadByte ();
986 framerate = MSG_ReadByte ();
988 CL_Effect(org, modelindex, startframe, framecount, framerate);
992 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
994 static qbyte cgamenetbuffer[65536];
997 =====================
998 CL_ParseServerMessage
999 =====================
1001 void CL_ParseServerMessage (void)
1004 int i, entitiesupdated;
1006 char *cmdlogname[32], *temp;
1007 int cmdindex, cmdcount = 0;
1010 // if recording demos, copy the message out
1012 if (cl_shownet.integer == 1)
1013 Con_Printf ("%i ",net_message.cursize);
1014 else if (cl_shownet.integer == 2)
1015 Con_Printf ("------------------\n");
1017 cl.onground = false; // unless the server says otherwise
1019 // parse the message
1021 MSG_BeginReading ();
1023 entitiesupdated = false;
1028 Host_Error ("CL_ParseServerMessage: Bad server message");
1030 cmd = MSG_ReadByte ();
1034 SHOWNET("END OF MESSAGE");
1035 break; // end of message
1038 cmdindex = cmdcount & 31;
1040 cmdlog[cmdindex] = cmd;
1042 // if the high bit of the command byte is set, it is a fast update
1045 // 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)
1047 cmdlogname[cmdindex] = temp;
1048 SHOWNET("fast update");
1049 if (cls.signon == SIGNONS - 1)
1051 // first update is the final signon stage
1052 cls.signon = SIGNONS;
1055 CL_ParseUpdate (cmd&127);
1059 SHOWNET(svc_strings[cmd]);
1060 cmdlogname[cmdindex] = svc_strings[cmd];
1061 if (!cmdlogname[cmdindex])
1063 // 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)
1065 cmdlogname[cmdindex] = temp;
1073 char description[32*64], temp[64];
1075 strcpy(description, "packet dump: ");
1079 count = cmdcount - i;
1083 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1084 strcat(description, temp);
1089 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1090 Con_Printf("%s", description);
1091 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1099 if (!entitiesupdated)
1101 // this is a new frame, we'll be seeing entities,
1102 // so prepare for entity updates
1103 CL_EntityUpdateSetup();
1104 entitiesupdated = true;
1106 cl.mtime[1] = cl.mtime[0];
1107 cl.mtime[0] = MSG_ReadFloat ();
1110 case svc_clientdata:
1111 i = MSG_ReadShort ();
1112 CL_ParseClientdata (i);
1116 i = MSG_ReadLong ();
1117 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1118 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1119 Nehahrademcompatibility = false;
1121 Nehahrademcompatibility = true;
1122 if (cls.demoplayback && demo_nehahra.integer)
1123 Nehahrademcompatibility = true;
1125 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1129 case svc_disconnect:
1130 Host_EndGame ("Server disconnected\n");
1133 Con_Printf ("%s", MSG_ReadString ());
1136 case svc_centerprint:
1137 SCR_CenterPrint (MSG_ReadString ());
1141 Cbuf_AddText (MSG_ReadString ());
1148 case svc_serverinfo:
1149 CL_ParseServerInfo ();
1153 for (i=0 ; i<3 ; i++)
1154 cl.viewangles[i] = MSG_ReadAngle ();
1158 cl.viewentity = MSG_ReadShort ();
1159 // LordHavoc: assume first setview recieved is the real player entity
1160 if (!cl.playerentity)
1161 cl.playerentity = cl.viewentity;
1164 case svc_lightstyle:
1165 i = MSG_ReadByte ();
1166 if (i >= MAX_LIGHTSTYLES)
1167 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1168 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1169 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1170 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1174 CL_ParseStartSoundPacket(false);
1178 CL_ParseStartSoundPacket(true);
1182 i = MSG_ReadShort();
1183 S_StopSound(i>>3, i&7);
1186 case svc_updatename:
1187 i = MSG_ReadByte ();
1188 if (i >= cl.maxclients)
1189 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1190 strcpy (cl.scores[i].name, MSG_ReadString ());
1193 case svc_updatefrags:
1194 i = MSG_ReadByte ();
1195 if (i >= cl.maxclients)
1196 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1197 cl.scores[i].frags = MSG_ReadShort ();
1200 case svc_updatecolors:
1201 i = MSG_ReadByte ();
1202 if (i >= cl.maxclients)
1203 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1204 cl.scores[i].colors = MSG_ReadByte ();
1205 // update our color cvar if our color changed
1206 if (i == cl.playerentity - 1)
1207 Cvar_SetValue ("_cl_color", cl.scores[i].colors);
1211 CL_ParseParticleEffect ();
1222 case svc_spawnbaseline:
1223 i = MSG_ReadShort ();
1224 if (i < 0 || i >= MAX_EDICTS)
1225 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1226 CL_ParseBaseline (cl_entities + i, false);
1228 case svc_spawnbaseline2:
1229 i = MSG_ReadShort ();
1230 if (i < 0 || i >= MAX_EDICTS)
1231 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1232 CL_ParseBaseline (cl_entities + i, true);
1234 case svc_spawnstatic:
1235 CL_ParseStatic (false);
1237 case svc_spawnstatic2:
1238 CL_ParseStatic (true);
1240 case svc_temp_entity:
1245 cl.paused = MSG_ReadByte ();
1253 i = MSG_ReadByte ();
1254 if (i <= cls.signon)
1255 Host_Error ("Received signon %i when at %i", i, cls.signon);
1260 case svc_killedmonster:
1261 cl.stats[STAT_MONSTERS]++;
1264 case svc_foundsecret:
1265 cl.stats[STAT_SECRETS]++;
1268 case svc_updatestat:
1269 i = MSG_ReadByte ();
1270 if (i < 0 || i >= MAX_CL_STATS)
1271 Host_Error ("svc_updatestat: %i is invalid", i);
1272 cl.stats[i] = MSG_ReadLong ();
1275 case svc_spawnstaticsound:
1276 CL_ParseStaticSound (false);
1279 case svc_spawnstaticsound2:
1280 CL_ParseStaticSound (true);
1284 cl.cdtrack = MSG_ReadByte ();
1285 cl.looptrack = MSG_ReadByte ();
1286 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1287 CDAudio_Play ((qbyte)cls.forcetrack, true);
1289 CDAudio_Play ((qbyte)cl.cdtrack, true);
1292 case svc_intermission:
1293 cl.intermission = 1;
1294 cl.completed_time = cl.time;
1298 cl.intermission = 2;
1299 cl.completed_time = cl.time;
1300 SCR_CenterPrint (MSG_ReadString ());
1304 cl.intermission = 3;
1305 cl.completed_time = cl.time;
1306 SCR_CenterPrint (MSG_ReadString ());
1309 case svc_sellscreen:
1310 Cmd_ExecuteString ("help", src_command);
1313 SHOWLMP_decodehide();
1316 SHOWLMP_decodeshow();
1319 R_SetSkyBox(MSG_ReadString());
1324 length = (int) ((unsigned short) MSG_ReadShort());
1325 for (i = 0;i < length;i++)
1326 cgamenetbuffer[i] = MSG_ReadByte();
1328 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1332 if (cls.signon == SIGNONS - 1)
1334 // first update is the final signon stage
1335 cls.signon = SIGNONS;
1338 CL_ReadEntityFrame();
1343 if (entitiesupdated)
1344 CL_EntityUpdateEnd();