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 if (!COM_ParseToken(&data))
232 if (com_token[0] != '{')
236 if (!COM_ParseToken(&data))
238 if (com_token[0] == '}')
239 break; // end of worldspawn
240 if (com_token[0] == '_')
241 strcpy(key, com_token + 1);
243 strcpy(key, com_token);
244 while (key[strlen(key)-1] == ' ') // remove trailing spaces
245 key[strlen(key)-1] = 0;
246 if (!COM_ParseToken(&data))
248 strcpy(value, com_token);
249 if (!strcmp("sky", key))
251 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
253 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
255 else if (!strcmp("fog", key))
256 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
257 else if (!strcmp("fog_density", key))
258 fog_density = atof(value);
259 else if (!strcmp("fog_red", key))
260 fog_red = atof(value);
261 else if (!strcmp("fog_green", key))
262 fog_green = atof(value);
263 else if (!strcmp("fog_blue", key))
264 fog_blue = atof(value);
269 =====================
272 An svc_signonnum has been received, perform a client side setup
273 =====================
275 static void CL_SignonReply (void)
279 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
284 MSG_WriteByte (&cls.message, clc_stringcmd);
285 MSG_WriteString (&cls.message, "prespawn");
289 MSG_WriteByte (&cls.message, clc_stringcmd);
290 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
292 MSG_WriteByte (&cls.message, clc_stringcmd);
293 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
295 if (cl_pmodel.integer)
297 MSG_WriteByte (&cls.message, clc_stringcmd);
298 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
301 MSG_WriteByte (&cls.message, clc_stringcmd);
302 //sprintf (str, "spawn %s", cls.spawnparms);
303 //MSG_WriteString (&cls.message, str);
304 MSG_WriteString (&cls.message, "spawn");
308 MSG_WriteByte (&cls.message, clc_stringcmd);
309 MSG_WriteString (&cls.message, "begin");
323 qbyte entlife[MAX_EDICTS];
324 void CL_ParseServerInfo (void)
328 int nummodels, numsounds;
329 char model_precache[MAX_MODELS][MAX_QPATH];
330 char sound_precache[MAX_SOUNDS][MAX_QPATH];
333 Con_DPrintf ("Serverinfo packet received.\n");
335 // wipe the client_state_t struct
339 // parse protocol version number
341 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
343 Con_Printf ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
346 Nehahrademcompatibility = false;
348 Nehahrademcompatibility = true;
349 if (cls.demoplayback && demo_nehahra.integer)
350 Nehahrademcompatibility = true;
352 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
356 cl.maxclients = MSG_ReadByte ();
357 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
359 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
362 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
365 cl.gametype = MSG_ReadByte ();
367 // parse signon message
368 str = MSG_ReadString ();
369 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
371 // seperate the printfs so the server message can have a color
372 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
374 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");
375 Con_Printf ("%c%s\n", 2, str);
379 // first we go through and touch all of the precache data that still
380 // happens to be in the cache, so precaching something else doesn't
381 // needlessly purge it
384 Mem_CheckSentinelsGlobal();
388 // disable until we get textures for it
392 memset (cl.model_precache, 0, sizeof(cl.model_precache));
393 for (nummodels=1 ; ; nummodels++)
395 str = MSG_ReadString ();
398 if (nummodels==MAX_MODELS)
400 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);
437 if (cl.model_precache[i] == NULL)
439 Con_Printf("Model %s not found\n", model_precache[i]);
442 CL_KeepaliveMessage ();
445 S_BeginPrecaching ();
446 for (i=1 ; i<numsounds ; i++)
448 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
449 CL_KeepaliveMessage ();
454 ent = &cl_entities[0];
455 // entire entity array was cleared, so just fill in a few fields
456 ent->state_current.active = true;
457 ent->render.model = cl.worldmodel = cl.model_precache[1];
458 ent->render.scale = 1;
459 ent->render.alpha = 1;
460 CL_BoundingBoxForEntity(&ent->render);
461 // clear entlife array
462 memset(entlife, 0, MAX_EDICTS);
469 noclip_anglehack = false; // noclip is turned off at start
471 Mem_CheckSentinelsGlobal();
475 void CL_ValidateState(entity_state_t *s)
482 if (s->modelindex >= MAX_MODELS)
483 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
485 // colormap is client index + 1
486 if (s->colormap > cl.maxclients)
487 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
489 model = cl.model_precache[s->modelindex];
490 Mod_CheckLoaded(model);
491 if (model && s->frame >= model->numframes)
493 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
496 if (model && s->skin > 0 && s->skin >= model->numskins)
498 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
503 void CL_MoveLerpEntityStates(entity_t *ent)
505 float odelta[3], adelta[3];
506 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
507 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
508 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
510 // we definitely shouldn't lerp
511 ent->persistent.lerpdeltatime = 0;
512 ent->persistent.lerpstarttime = cl.mtime[1];
513 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
514 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
515 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
516 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
518 else// if (ent->state_current.flags & RENDER_STEP)
520 // monster interpolation
521 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
523 ent->persistent.lerpdeltatime = cl.time - ent->persistent.lerpstarttime;
524 ent->persistent.lerpstarttime = cl.mtime[1];
525 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
526 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
527 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
528 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
535 ent->persistent.lerpstarttime = cl.mtime[1];
536 // no lerp if it's singleplayer
537 //if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
538 // ent->persistent.lerpdeltatime = 0;
540 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
541 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
542 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
543 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
544 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
553 Parse an entity update message from the server
554 If an entities model or origin changes from frame to frame, it must be
555 relinked. Other attributes can change without relinking.
558 int bitprofile[32], bitprofilecount = 0;
559 void CL_ParseUpdate (int bits)
565 if (bits & U_MOREBITS)
566 bits |= (MSG_ReadByte()<<8);
567 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
569 bits |= MSG_ReadByte() << 16;
570 if (bits & U_EXTEND2)
571 bits |= MSG_ReadByte() << 24;
574 if (bits & U_LONGENTITY)
575 num = (unsigned) MSG_ReadShort ();
577 num = (unsigned) MSG_ReadByte ();
579 if (num >= MAX_EDICTS)
580 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
582 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
584 ent = cl_entities + num;
586 for (i = 0;i < 32;i++)
591 // note: this inherits the 'active' state of the baseline chosen
592 // (state_baseline is always active, state_current may not be active if
593 // the entity was missing in the last frame)
595 new = ent->state_current;
598 new = ent->state_baseline;
603 new.time = cl.mtime[0];
605 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
606 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
607 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
608 if (bits & U_SKIN) new.skin = MSG_ReadByte();
609 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
610 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
611 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
612 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
613 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
614 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
615 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
616 if (bits & U_STEP) new.flags |= RENDER_STEP;
617 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
618 if (bits & U_SCALE) new.scale = MSG_ReadByte();
619 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
620 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
621 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
622 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
623 if (bits & U_COLORMOD) MSG_ReadByte();
624 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
625 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
626 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
627 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
628 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
630 // LordHavoc: to allow playback of the Nehahra movie
631 if (Nehahrademcompatibility && (bits & U_EXTEND1))
633 // LordHavoc: evil format
634 int i = MSG_ReadFloat();
635 int j = MSG_ReadFloat() * 255.0f;
640 new.effects |= EF_FULLBRIGHT;
644 else if (j == 0 || j >= 255)
651 CL_ValidateState(&new);
653 ent->state_previous = ent->state_current;
654 ent->state_current = new;
655 if (ent->state_current.active)
657 CL_MoveLerpEntityStates(ent);
658 cl_entities_active[ent->state_current.number] = true;
659 // mark as visible (no kill this frame)
660 entlife[ent->state_current.number] = 2;
664 void CL_ReadEntityFrame(void)
667 entity_frame_t entityframe;
669 EntityFrame_Read(&cl.entitydatabase);
670 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
671 for (i = 0;i < entityframe.numentities;i++)
674 ent = &cl_entities[entityframe.entitydata[i].number];
675 ent->state_previous = ent->state_current;
676 ent->state_current = entityframe.entitydata[i];
677 CL_MoveLerpEntityStates(ent);
678 // the entity lives again...
679 entlife[ent->state_current.number] = 2;
680 cl_entities_active[ent->state_current.number] = true;
682 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
683 VectorCopy(entityframe.eye, cl.viewentoriginnew);
686 char *bitprofilenames[32] =
710 "obsolete U_COLORMOD",
722 void CL_BitProfile_f(void)
725 Con_Printf("bitprofile: %i updates\n");
727 for (i = 0;i < 32;i++)
728 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
730 for (i = 0;i < 32;i++)
735 void CL_EntityUpdateSetup(void)
739 void CL_EntityUpdateEnd(void)
742 // disable entities that disappeared this frame
743 for (i = 1;i < MAX_EDICTS;i++)
745 // clear only the entities that were active last frame but not this
746 // frame, don't waste time clearing all entities (which would cause
752 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
762 void CL_ParseBaseline (entity_t *ent, int large)
766 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
767 ent->state_baseline.active = true;
770 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
771 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
775 ent->state_baseline.modelindex = MSG_ReadByte ();
776 ent->state_baseline.frame = MSG_ReadByte ();
778 ent->state_baseline.colormap = MSG_ReadByte();
779 ent->state_baseline.skin = MSG_ReadByte();
780 for (i = 0;i < 3;i++)
782 ent->state_baseline.origin[i] = MSG_ReadCoord ();
783 ent->state_baseline.angles[i] = MSG_ReadAngle ();
785 ent->state_baseline.alpha = 255;
786 ent->state_baseline.scale = 16;
787 ent->state_baseline.glowsize = 0;
788 ent->state_baseline.glowcolor = 254;
789 ent->state_previous = ent->state_current = ent->state_baseline;
791 CL_ValidateState(&ent->state_baseline);
799 Server information pertaining to this client only
802 void CL_ParseClientdata (int bits)
807 if (bits & SU_EXTEND1)
808 bits |= (MSG_ReadByte() << 16);
809 if (bits & SU_EXTEND2)
810 bits |= (MSG_ReadByte() << 24);
812 if (bits & SU_VIEWHEIGHT)
813 cl.viewheight = MSG_ReadChar ();
815 cl.viewheight = DEFAULT_VIEWHEIGHT;
817 if (bits & SU_IDEALPITCH)
818 cl.idealpitch = MSG_ReadChar ();
822 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
823 for (i=0 ; i<3 ; i++)
825 if (bits & (SU_PUNCH1<<i) )
828 cl.punchangle[i] = MSG_ReadPreciseAngle();
830 cl.punchangle[i] = MSG_ReadChar();
833 cl.punchangle[i] = 0;
834 if (bits & (SU_PUNCHVEC1<<i))
835 cl.punchvector[i] = MSG_ReadCoord();
837 cl.punchvector[i] = 0;
838 if (bits & (SU_VELOCITY1<<i) )
839 cl.mvelocity[0][i] = MSG_ReadChar()*16;
841 cl.mvelocity[0][i] = 0;
847 for (j=0 ; j<32 ; j++)
848 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
849 cl.item_gettime[j] = cl.time;
853 cl.onground = (bits & SU_ONGROUND) != 0;
854 cl.inwater = (bits & SU_INWATER) != 0;
856 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
857 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
858 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
859 cl.stats[STAT_HEALTH] = MSG_ReadShort();
860 cl.stats[STAT_AMMO] = MSG_ReadByte();
862 cl.stats[STAT_SHELLS] = MSG_ReadByte();
863 cl.stats[STAT_NAILS] = MSG_ReadByte();
864 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
865 cl.stats[STAT_CELLS] = MSG_ReadByte();
869 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
870 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
872 cl.stats[STAT_ACTIVEWEAPON] = i;
874 cl.viewzoomold = cl.viewzoomnew; // for interpolation
875 if (bits & SU_VIEWZOOM)
880 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
888 =====================
890 =====================
892 void CL_ParseStatic (int large)
896 if (cl_num_static_entities >= cl_max_static_entities)
897 Host_Error ("Too many static entities");
898 ent = &cl_static_entities[cl_num_static_entities++];
899 CL_ParseBaseline (ent, large);
901 // copy it to the current state
902 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
903 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
904 ent->render.framelerp = 0;
905 // make torchs play out of sync
906 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
907 ent->render.colormap = -1; // no special coloring
908 ent->render.skinnum = ent->state_baseline.skin;
909 ent->render.effects = ent->state_baseline.effects;
910 ent->render.alpha = 1;
911 ent->render.scale = 1;
912 ent->render.alpha = 1;
914 VectorCopy (ent->state_baseline.origin, ent->render.origin);
915 VectorCopy (ent->state_baseline.angles, ent->render.angles);
917 CL_BoundingBoxForEntity(&ent->render);
919 // This is definitely cheating...
920 if (ent->render.model == NULL)
921 cl_num_static_entities--;
929 void CL_ParseStaticSound (int large)
932 int sound_num, vol, atten;
936 sound_num = (unsigned short) MSG_ReadShort ();
938 sound_num = MSG_ReadByte ();
939 vol = MSG_ReadByte ();
940 atten = MSG_ReadByte ();
942 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
945 void CL_ParseEffect (void)
948 int modelindex, startframe, framecount, framerate;
951 modelindex = MSG_ReadByte ();
952 startframe = MSG_ReadByte ();
953 framecount = MSG_ReadByte ();
954 framerate = MSG_ReadByte ();
956 CL_Effect(org, modelindex, startframe, framecount, framerate);
959 void CL_ParseEffect2 (void)
962 int modelindex, startframe, framecount, framerate;
965 modelindex = MSG_ReadShort ();
966 startframe = MSG_ReadShort ();
967 framecount = MSG_ReadByte ();
968 framerate = MSG_ReadByte ();
970 CL_Effect(org, modelindex, startframe, framecount, framerate);
974 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
976 static qbyte cgamenetbuffer[65536];
979 =====================
980 CL_ParseServerMessage
981 =====================
983 void CL_ParseServerMessage (void)
986 int i, entitiesupdated;
988 char *cmdlogname[32], *temp;
989 int cmdindex, cmdcount = 0;
992 // if recording demos, copy the message out
994 if (cl_shownet.integer == 1)
995 Con_Printf ("%i ",net_message.cursize);
996 else if (cl_shownet.integer == 2)
997 Con_Printf ("------------------\n");
999 cl.onground = false; // unless the server says otherwise
1001 // parse the message
1003 MSG_BeginReading ();
1005 entitiesupdated = false;
1010 Host_Error ("CL_ParseServerMessage: Bad server message");
1012 cmd = MSG_ReadByte ();
1016 SHOWNET("END OF MESSAGE");
1017 break; // end of message
1020 cmdindex = cmdcount & 31;
1022 cmdlog[cmdindex] = cmd;
1024 // if the high bit of the command byte is set, it is a fast update
1027 // 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)
1029 cmdlogname[cmdindex] = temp;
1030 SHOWNET("fast update");
1031 if (cls.signon == SIGNONS - 1)
1033 // first update is the final signon stage
1034 cls.signon = SIGNONS;
1037 CL_ParseUpdate (cmd&127);
1041 SHOWNET(svc_strings[cmd]);
1042 cmdlogname[cmdindex] = svc_strings[cmd];
1043 if (!cmdlogname[cmdindex])
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;
1055 char description[32*64], temp[64];
1057 strcpy(description, "packet dump: ");
1061 count = cmdcount - i;
1065 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1066 strcat(description, temp);
1071 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1072 Con_Printf("%s", description);
1073 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1081 if (!entitiesupdated)
1083 // this is a new frame, we'll be seeing entities,
1084 // so prepare for entity updates
1085 CL_EntityUpdateSetup();
1086 entitiesupdated = true;
1088 cl.mtime[1] = cl.mtime[0];
1089 cl.mtime[0] = MSG_ReadFloat ();
1092 case svc_clientdata:
1093 i = MSG_ReadShort ();
1094 CL_ParseClientdata (i);
1098 i = MSG_ReadLong ();
1099 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1100 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1101 Nehahrademcompatibility = false;
1103 Nehahrademcompatibility = true;
1104 if (cls.demoplayback && demo_nehahra.integer)
1105 Nehahrademcompatibility = true;
1107 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1111 case svc_disconnect:
1112 Host_EndGame ("Server disconnected\n");
1115 Con_Printf ("%s", MSG_ReadString ());
1118 case svc_centerprint:
1119 SCR_CenterPrint (MSG_ReadString ());
1123 Cbuf_AddText (MSG_ReadString ());
1130 case svc_serverinfo:
1131 CL_ParseServerInfo ();
1135 for (i=0 ; i<3 ; i++)
1136 cl.viewangles[i] = MSG_ReadAngle ();
1140 cl.viewentity = MSG_ReadShort ();
1141 // LordHavoc: assume first setview recieved is the real player entity
1142 if (!cl.playerentity)
1143 cl.playerentity = cl.viewentity;
1146 case svc_lightstyle:
1147 i = MSG_ReadByte ();
1148 if (i >= MAX_LIGHTSTYLES)
1149 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1150 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1151 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1152 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1156 CL_ParseStartSoundPacket(false);
1160 CL_ParseStartSoundPacket(true);
1164 i = MSG_ReadShort();
1165 S_StopSound(i>>3, i&7);
1168 case svc_updatename:
1169 i = MSG_ReadByte ();
1170 if (i >= cl.maxclients)
1171 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1172 strcpy (cl.scores[i].name, MSG_ReadString ());
1175 case svc_updatefrags:
1176 i = MSG_ReadByte ();
1177 if (i >= cl.maxclients)
1178 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1179 cl.scores[i].frags = MSG_ReadShort ();
1182 case svc_updatecolors:
1183 i = MSG_ReadByte ();
1184 if (i >= cl.maxclients)
1185 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1186 cl.scores[i].colors = MSG_ReadByte ();
1187 // update our color cvar if our color changed
1188 if (i == cl.playerentity - 1)
1189 Cvar_SetValue ("_cl_color", cl.scores[i].colors);
1193 CL_ParseParticleEffect ();
1204 case svc_spawnbaseline:
1205 i = MSG_ReadShort ();
1206 if (i < 0 || i >= MAX_EDICTS)
1207 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1208 CL_ParseBaseline (cl_entities + i, false);
1210 case svc_spawnbaseline2:
1211 i = MSG_ReadShort ();
1212 if (i < 0 || i >= MAX_EDICTS)
1213 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1214 CL_ParseBaseline (cl_entities + i, true);
1216 case svc_spawnstatic:
1217 CL_ParseStatic (false);
1219 case svc_spawnstatic2:
1220 CL_ParseStatic (true);
1222 case svc_temp_entity:
1227 cl.paused = MSG_ReadByte ();
1235 i = MSG_ReadByte ();
1236 if (i <= cls.signon)
1237 Host_Error ("Received signon %i when at %i", i, cls.signon);
1242 case svc_killedmonster:
1243 cl.stats[STAT_MONSTERS]++;
1246 case svc_foundsecret:
1247 cl.stats[STAT_SECRETS]++;
1250 case svc_updatestat:
1251 i = MSG_ReadByte ();
1252 if (i < 0 || i >= MAX_CL_STATS)
1253 Host_Error ("svc_updatestat: %i is invalid", i);
1254 cl.stats[i] = MSG_ReadLong ();
1257 case svc_spawnstaticsound:
1258 CL_ParseStaticSound (false);
1261 case svc_spawnstaticsound2:
1262 CL_ParseStaticSound (true);
1266 cl.cdtrack = MSG_ReadByte ();
1267 cl.looptrack = MSG_ReadByte ();
1268 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1269 CDAudio_Play ((qbyte)cls.forcetrack, true);
1271 CDAudio_Play ((qbyte)cl.cdtrack, true);
1274 case svc_intermission:
1275 cl.intermission = 1;
1276 cl.completed_time = cl.time;
1280 cl.intermission = 2;
1281 cl.completed_time = cl.time;
1282 SCR_CenterPrint (MSG_ReadString ());
1286 cl.intermission = 3;
1287 cl.completed_time = cl.time;
1288 SCR_CenterPrint (MSG_ReadString ());
1291 case svc_sellscreen:
1292 Cmd_ExecuteString ("help", src_command);
1295 SHOWLMP_decodehide();
1298 SHOWLMP_decodeshow();
1301 R_SetSkyBox(MSG_ReadString());
1306 length = (int) ((unsigned short) MSG_ReadShort());
1307 for (i = 0;i < length;i++)
1308 cgamenetbuffer[i] = MSG_ReadByte();
1310 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1314 if (cls.signon == SIGNONS - 1)
1316 // first update is the final signon stage
1317 cls.signon = SIGNONS;
1320 CL_ReadEntityFrame();
1325 if (entitiesupdated)
1326 CL_EntityUpdateEnd();