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
114 This error checks and tracks the total number of entities
117 entity_t *CL_EntityNum (int num)
119 if (num >= MAX_EDICTS)
120 Host_Error ("CL_EntityNum: %i is an invalid number",num);
122 return &cl_entities[num];
128 CL_ParseStartSoundPacket
131 void CL_ParseStartSoundPacket(int largesoundindex)
141 field_mask = MSG_ReadByte();
143 if (field_mask & SND_VOLUME)
144 volume = MSG_ReadByte ();
146 volume = DEFAULT_SOUND_PACKET_VOLUME;
148 if (field_mask & SND_ATTENUATION)
149 attenuation = MSG_ReadByte () / 64.0;
151 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
153 channel = MSG_ReadShort ();
155 sound_num = (unsigned short) MSG_ReadShort ();
157 sound_num = MSG_ReadByte ();
159 if (sound_num >= MAX_SOUNDS)
160 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
165 if (ent > MAX_EDICTS)
166 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
168 for (i=0 ; i<3 ; i++)
169 pos[i] = MSG_ReadCoord ();
171 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
178 When the client is taking a long time to load stuff, send keepalive messages
179 so the server doesn't disconnect.
182 void CL_KeepaliveMessage (void)
185 static float lastmsg;
192 return; // no need if server is local
193 if (cls.demoplayback)
196 // read messages from server, should just be nops
198 memcpy (olddata, net_message.data, net_message.cursize);
202 ret = CL_GetMessage ();
206 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
208 break; // nothing waiting
210 Host_Error ("CL_KeepaliveMessage: received a message");
215 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
221 memcpy (net_message.data, olddata, net_message.cursize);
224 time = Sys_DoubleTime ();
225 if (time - lastmsg < 5)
230 Con_Printf ("--> client to server keepalive\n");
232 MSG_WriteByte (&cls.message, clc_nop);
233 NET_SendMessage (cls.netcon, &cls.message);
234 SZ_Clear (&cls.message);
237 void CL_ParseEntityLump(char *entdata)
240 char key[128], value[4096];
241 FOG_clear(); // LordHavoc: no fog until set
242 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
246 data = COM_Parse(data);
249 if (com_token[0] != '{')
253 data = COM_Parse(data);
256 if (com_token[0] == '}')
257 break; // end of worldspawn
258 if (com_token[0] == '_')
259 strcpy(key, com_token + 1);
261 strcpy(key, com_token);
262 while (key[strlen(key)-1] == ' ') // remove trailing spaces
263 key[strlen(key)-1] = 0;
264 data = COM_Parse(data);
267 strcpy(value, com_token);
268 if (!strcmp("sky", key))
270 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
272 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
274 else if (!strcmp("fog", key))
275 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
276 else if (!strcmp("fog_density", key))
277 fog_density = atof(value);
278 else if (!strcmp("fog_red", key))
279 fog_red = atof(value);
280 else if (!strcmp("fog_green", key))
281 fog_green = atof(value);
282 else if (!strcmp("fog_blue", key))
283 fog_blue = atof(value);
288 =====================
291 An svc_signonnum has been received, perform a client side setup
292 =====================
294 static void CL_SignonReply (void)
298 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
303 MSG_WriteByte (&cls.message, clc_stringcmd);
304 MSG_WriteString (&cls.message, "prespawn");
308 MSG_WriteByte (&cls.message, clc_stringcmd);
309 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
311 MSG_WriteByte (&cls.message, clc_stringcmd);
312 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
314 if (cl_pmodel.integer)
316 MSG_WriteByte (&cls.message, clc_stringcmd);
317 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
320 MSG_WriteByte (&cls.message, clc_stringcmd);
321 //sprintf (str, "spawn %s", cls.spawnparms);
322 //MSG_WriteString (&cls.message, str);
323 MSG_WriteString (&cls.message, "spawn");
327 MSG_WriteByte (&cls.message, clc_stringcmd);
328 MSG_WriteString (&cls.message, "begin");
342 void CL_ParseServerInfo (void)
346 int nummodels, numsounds;
347 char model_precache[MAX_MODELS][MAX_QPATH];
348 char sound_precache[MAX_SOUNDS][MAX_QPATH];
351 Con_DPrintf ("Serverinfo packet received.\n");
353 // wipe the client_state_t struct
357 // parse protocol version number
359 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
361 Con_Printf ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
364 Nehahrademcompatibility = false;
366 Nehahrademcompatibility = true;
367 if (cls.demoplayback && demo_nehahra.integer)
368 Nehahrademcompatibility = true;
370 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
374 cl.maxclients = MSG_ReadByte ();
375 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
377 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
380 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
383 cl.gametype = MSG_ReadByte ();
385 // parse signon message
386 str = MSG_ReadString ();
387 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
389 // seperate the printfs so the server message can have a color
390 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
392 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");
393 Con_Printf ("%c%s\n", 2, str);
397 // first we go through and touch all of the precache data that still
398 // happens to be in the cache, so precaching something else doesn't
399 // needlessly purge it
402 Mem_CheckSentinelsGlobal();
407 memset (cl.model_precache, 0, sizeof(cl.model_precache));
408 for (nummodels=1 ; ; nummodels++)
410 str = MSG_ReadString ();
413 if (nummodels==MAX_MODELS)
415 Host_Error ("Server sent too many model precaches\n");
418 if (strlen(str) >= MAX_QPATH)
419 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
420 strcpy (model_precache[nummodels], str);
421 Mod_TouchModel (str);
425 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
426 for (numsounds=1 ; ; numsounds++)
428 str = MSG_ReadString ();
431 if (numsounds==MAX_SOUNDS)
433 Host_Error ("Server sent too many sound precaches\n");
436 if (strlen(str) >= MAX_QPATH)
437 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
438 strcpy (sound_precache[numsounds], str);
445 // now we try to load everything else until a cache allocation fails
448 for (i=1 ; i<nummodels ; i++)
450 // LordHavoc: i == 1 means the first model is the world model
451 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
453 if (cl.model_precache[i] == NULL)
455 Host_Error("Model %s not found\n", model_precache[i]);
458 CL_KeepaliveMessage ();
461 S_BeginPrecaching ();
462 for (i=1 ; i<numsounds ; i++)
464 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
465 CL_KeepaliveMessage ();
470 ent = &cl_entities[0];
471 memset(ent, 0, sizeof(entity_t));
472 ent->render.model = cl.worldmodel = cl.model_precache[1];
473 ent->render.scale = 1;
474 ent->render.alpha = 1;
476 if (ent->render.angles[0] || ent->render.angles[2])
479 VectorAdd(ent->render.origin, ent->render.model->rotatedmins, ent->render.mins);
480 VectorAdd(ent->render.origin, ent->render.model->rotatedmaxs, ent->render.maxs);
482 else if (ent->render.angles[1])
485 VectorAdd(ent->render.origin, ent->render.model->yawmins, ent->render.mins);
486 VectorAdd(ent->render.origin, ent->render.model->yawmaxs, ent->render.maxs);
490 VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins);
491 VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs);
500 Mem_CheckSentinelsGlobal();
502 noclip_anglehack = false; // noclip is turned off at start
505 void CL_ValidateState(entity_state_t *s)
512 if (s->modelindex >= MAX_MODELS)
513 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
515 // colormap is client index + 1
516 if (s->colormap > cl.maxclients)
517 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
519 model = cl.model_precache[s->modelindex];
520 Mod_CheckLoaded(model);
521 if (model && s->frame >= model->numframes)
523 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
526 if (model && s->skin > 0 && s->skin >= model->numskins)
528 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
537 Parse an entity update message from the server
538 If an entities model or origin changes from frame to frame, it must be
539 relinked. Other attributes can change without relinking.
542 qbyte entkill[MAX_EDICTS];
543 int bitprofile[32], bitprofilecount = 0;
544 void CL_ParseUpdate (int bits)
546 int i, num, deltadie;
550 if (bits & U_MOREBITS)
551 bits |= (MSG_ReadByte()<<8);
552 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
554 bits |= MSG_ReadByte() << 16;
555 if (bits & U_EXTEND2)
556 bits |= MSG_ReadByte() << 24;
559 if (bits & U_LONGENTITY)
560 num = (unsigned) MSG_ReadShort ();
562 num = (unsigned) MSG_ReadByte ();
564 if (num >= MAX_EDICTS)
565 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
567 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
569 // mark as visible (no kill)
572 ent = CL_EntityNum (num);
574 for (i = 0;i < 32;i++)
582 new = ent->state_current;
584 deltadie = true; // was not present in previous frame, leave hidden until next full update
587 new = ent->state_baseline;
589 new.time = cl.mtime[0];
593 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
594 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
595 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
596 if (bits & U_SKIN) new.skin = MSG_ReadByte();
597 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
598 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
599 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
600 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
601 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
602 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
603 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
604 if (bits & U_STEP) new.flags |= RENDER_STEP;
605 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
606 if (bits & U_SCALE) new.scale = MSG_ReadByte();
607 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
608 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
609 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
610 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
611 if (bits & U_COLORMOD) MSG_ReadByte();
612 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
613 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
614 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
615 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
616 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
618 // LordHavoc: to allow playback of the Nehahra movie
619 if (Nehahrademcompatibility && (bits & U_EXTEND1))
621 // LordHavoc: evil format
622 int i = MSG_ReadFloat();
623 int j = MSG_ReadFloat() * 255.0f;
628 new.effects |= EF_FULLBRIGHT;
632 else if (j == 0 || j >= 255)
644 CL_ValidateState(&new);
646 if (new.flags & RENDER_STEP) // FIXME: rename this flag?
648 // make time identical for memcmp
649 new.time = ent->state_current.time;
650 if (memcmp(&new, &ent->state_current, sizeof(entity_state_t)))
652 // set it back to what it should be
653 new.time = cl.mtime[0] + 0.1;
655 ent->state_previous = ent->state_current;
656 ent->state_current = new;
657 // assume 10fps animation
658 //ent->state_previous.time = cl.mtime[0] - 0.1;
663 ent->state_previous = ent->state_current;
664 ent->state_current = new;
668 void CL_ReadEntityFrame(void)
672 entity_frame_t entityframe;
674 EntityFrame_Read(&cl.entitydatabase);
675 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
676 for (i = 0;i < entityframe.numentities;i++)
678 s = &entityframe.entitydata[i];
679 entkill[s->number] = 0;
680 ent = &cl_entities[s->number];
681 memcpy(&ent->state_previous, &ent->state_current, sizeof(*s));
682 memcpy(&ent->state_current, s, sizeof(*s));
683 ent->state_current.time = cl.mtime[0];
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)
740 memset(entkill, 1, MAX_EDICTS);
743 void CL_EntityUpdateEnd(void)
746 for (i = 1;i < MAX_EDICTS;i++)
748 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
756 void CL_ParseBaseline (entity_t *ent, int large)
760 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
761 ent->state_baseline.active = true;
764 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
765 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
769 ent->state_baseline.modelindex = MSG_ReadByte ();
770 ent->state_baseline.frame = MSG_ReadByte ();
772 ent->state_baseline.colormap = MSG_ReadByte();
773 ent->state_baseline.skin = MSG_ReadByte();
774 for (i = 0;i < 3;i++)
776 ent->state_baseline.origin[i] = MSG_ReadCoord ();
777 ent->state_baseline.angles[i] = MSG_ReadAngle ();
779 ent->state_baseline.alpha = 255;
780 ent->state_baseline.scale = 16;
781 ent->state_baseline.glowsize = 0;
782 ent->state_baseline.glowcolor = 254;
783 ent->state_previous = ent->state_current = ent->state_baseline;
785 CL_ValidateState(&ent->state_baseline);
793 Server information pertaining to this client only
796 void CL_ParseClientdata (int bits)
801 if (bits & SU_EXTEND1)
802 bits |= (MSG_ReadByte() << 16);
803 if (bits & SU_EXTEND2)
804 bits |= (MSG_ReadByte() << 24);
806 if (bits & SU_VIEWHEIGHT)
807 cl.viewheight = MSG_ReadChar ();
809 cl.viewheight = DEFAULT_VIEWHEIGHT;
811 if (bits & SU_IDEALPITCH)
812 cl.idealpitch = MSG_ReadChar ();
816 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
817 for (i=0 ; i<3 ; i++)
819 if (bits & (SU_PUNCH1<<i) )
822 cl.punchangle[i] = MSG_ReadPreciseAngle();
824 cl.punchangle[i] = MSG_ReadChar();
827 cl.punchangle[i] = 0;
828 if (bits & (SU_PUNCHVEC1<<i))
829 cl.punchvector[i] = MSG_ReadCoord();
831 cl.punchvector[i] = 0;
832 if (bits & (SU_VELOCITY1<<i) )
833 cl.mvelocity[0][i] = MSG_ReadChar()*16;
835 cl.mvelocity[0][i] = 0;
841 for (j=0 ; j<32 ; j++)
842 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
843 cl.item_gettime[j] = cl.time;
847 cl.onground = (bits & SU_ONGROUND) != 0;
848 cl.inwater = (bits & SU_INWATER) != 0;
850 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
851 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
852 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
853 cl.stats[STAT_HEALTH] = MSG_ReadShort();
854 cl.stats[STAT_AMMO] = MSG_ReadByte();
856 cl.stats[STAT_SHELLS] = MSG_ReadByte();
857 cl.stats[STAT_NAILS] = MSG_ReadByte();
858 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
859 cl.stats[STAT_CELLS] = MSG_ReadByte();
863 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
864 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
866 cl.stats[STAT_ACTIVEWEAPON] = i;
868 cl.viewzoomold = cl.viewzoomnew; // for interpolation
869 if (bits & SU_VIEWZOOM)
874 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
882 =====================
884 =====================
886 void CL_ParseStatic (int large)
890 if (cl_num_static_entities >= cl_max_static_entities)
891 Host_Error ("Too many static entities");
892 ent = &cl_static_entities[cl_num_static_entities++];
893 CL_ParseBaseline (ent, large);
895 // copy it to the current state
896 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
897 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
898 ent->render.framelerp = 0;
899 // make torchs play out of sync
900 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
901 ent->render.colormap = -1; // no special coloring
902 ent->render.skinnum = ent->state_baseline.skin;
903 ent->render.effects = ent->state_baseline.effects;
904 ent->render.alpha = 1;
905 ent->render.scale = 1;
906 ent->render.alpha = 1;
908 VectorCopy (ent->state_baseline.origin, ent->render.origin);
909 VectorCopy (ent->state_baseline.angles, ent->render.angles);
911 if (ent->render.angles[0] || ent->render.angles[2])
914 VectorAdd(ent->render.origin, ent->render.model->rotatedmins, ent->render.mins);
915 VectorAdd(ent->render.origin, ent->render.model->rotatedmaxs, ent->render.maxs);
917 else if (ent->render.angles[1])
920 VectorAdd(ent->render.origin, ent->render.model->yawmins, ent->render.mins);
921 VectorAdd(ent->render.origin, ent->render.model->yawmaxs, ent->render.maxs);
925 VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins);
926 VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs);
929 // This is definitely cheating...
930 if (ent->render.model == NULL)
931 cl_num_static_entities--;
939 void CL_ParseStaticSound (int large)
942 int sound_num, vol, atten;
946 sound_num = (unsigned short) MSG_ReadShort ();
948 sound_num = MSG_ReadByte ();
949 vol = MSG_ReadByte ();
950 atten = MSG_ReadByte ();
952 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
955 void CL_ParseEffect (void)
958 int modelindex, startframe, framecount, framerate;
961 modelindex = MSG_ReadByte ();
962 startframe = MSG_ReadByte ();
963 framecount = MSG_ReadByte ();
964 framerate = MSG_ReadByte ();
966 CL_Effect(org, modelindex, startframe, framecount, framerate);
969 void CL_ParseEffect2 (void)
972 int modelindex, startframe, framecount, framerate;
975 modelindex = MSG_ReadShort ();
976 startframe = MSG_ReadShort ();
977 framecount = MSG_ReadByte ();
978 framerate = MSG_ReadByte ();
980 CL_Effect(org, modelindex, startframe, framecount, framerate);
984 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
986 static qbyte cgamenetbuffer[65536];
989 =====================
990 CL_ParseServerMessage
991 =====================
993 void CL_ParseServerMessage (void)
996 int i, entitiesupdated;
998 char *cmdlogname[32], *temp;
999 int cmdindex, cmdcount = 0;
1002 // if recording demos, copy the message out
1004 if (cl_shownet.integer == 1)
1005 Con_Printf ("%i ",net_message.cursize);
1006 else if (cl_shownet.integer == 2)
1007 Con_Printf ("------------------\n");
1009 cl.onground = false; // unless the server says otherwise
1011 // parse the message
1013 MSG_BeginReading ();
1015 entitiesupdated = false;
1016 CL_EntityUpdateSetup();
1021 Host_Error ("CL_ParseServerMessage: Bad server message");
1023 cmd = MSG_ReadByte ();
1027 SHOWNET("END OF MESSAGE");
1028 break; // end of message
1031 cmdindex = cmdcount & 31;
1033 cmdlog[cmdindex] = cmd;
1035 // if the high bit of the command byte is set, it is a fast update
1038 // 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)
1040 cmdlogname[cmdindex] = temp;
1041 SHOWNET("fast update");
1042 if (cls.signon == SIGNONS - 1)
1043 { // first update is the final signon stage
1044 cls.signon = SIGNONS;
1047 CL_ParseUpdate (cmd&127);
1051 SHOWNET(svc_strings[cmd]);
1052 cmdlogname[cmdindex] = svc_strings[cmd];
1053 if (!cmdlogname[cmdindex])
1055 // 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)
1057 cmdlogname[cmdindex] = temp;
1065 char description[32*64], temp[64];
1067 strcpy(description, "packet dump: ");
1071 count = cmdcount - i;
1075 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1076 strcat(description, temp);
1081 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1082 Con_Printf("%s", description);
1083 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1091 // handle old protocols which do not have entity update ranges
1092 entitiesupdated = true;
1093 cl.mtime[1] = cl.mtime[0];
1094 cl.mtime[0] = MSG_ReadFloat ();
1097 case svc_clientdata:
1098 i = MSG_ReadShort ();
1099 CL_ParseClientdata (i);
1103 i = MSG_ReadLong ();
1104 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1105 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1106 Nehahrademcompatibility = false;
1108 Nehahrademcompatibility = true;
1109 if (cls.demoplayback && demo_nehahra.integer)
1110 Nehahrademcompatibility = true;
1112 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1116 case svc_disconnect:
1117 Host_EndGame ("Server disconnected\n");
1120 Con_Printf ("%s", MSG_ReadString ());
1123 case svc_centerprint:
1124 SCR_CenterPrint (MSG_ReadString ());
1128 Cbuf_AddText (MSG_ReadString ());
1135 case svc_serverinfo:
1136 CL_ParseServerInfo ();
1140 for (i=0 ; i<3 ; i++)
1141 cl.viewangles[i] = MSG_ReadAngle ();
1145 cl.viewentity = MSG_ReadShort ();
1148 case svc_lightstyle:
1149 i = MSG_ReadByte ();
1150 if (i >= MAX_LIGHTSTYLES)
1151 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1152 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1153 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1154 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1158 CL_ParseStartSoundPacket(false);
1162 CL_ParseStartSoundPacket(true);
1166 i = MSG_ReadShort();
1167 S_StopSound(i>>3, i&7);
1170 case svc_updatename:
1171 i = MSG_ReadByte ();
1172 if (i >= cl.maxclients)
1173 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1174 strcpy (cl.scores[i].name, MSG_ReadString ());
1177 case svc_updatefrags:
1178 i = MSG_ReadByte ();
1179 if (i >= cl.maxclients)
1180 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1181 cl.scores[i].frags = MSG_ReadShort ();
1184 case svc_updatecolors:
1185 i = MSG_ReadByte ();
1186 if (i >= cl.maxclients)
1187 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1188 cl.scores[i].colors = MSG_ReadByte ();
1192 CL_ParseParticleEffect ();
1203 case svc_spawnbaseline:
1204 i = MSG_ReadShort ();
1205 // must use CL_EntityNum() to force cl.num_entities up
1206 CL_ParseBaseline (CL_EntityNum(i), false);
1208 case svc_spawnbaseline2:
1209 i = MSG_ReadShort ();
1210 // must use CL_EntityNum() to force cl.num_entities up
1211 CL_ParseBaseline (CL_EntityNum(i), true);
1213 case svc_spawnstatic:
1214 CL_ParseStatic (false);
1216 case svc_spawnstatic2:
1217 CL_ParseStatic (true);
1219 case svc_temp_entity:
1224 cl.paused = MSG_ReadByte ();
1232 i = MSG_ReadByte ();
1233 if (i <= cls.signon)
1234 Host_Error ("Received signon %i when at %i", i, cls.signon);
1239 case svc_killedmonster:
1240 cl.stats[STAT_MONSTERS]++;
1243 case svc_foundsecret:
1244 cl.stats[STAT_SECRETS]++;
1247 case svc_updatestat:
1248 i = MSG_ReadByte ();
1249 if (i < 0 || i >= MAX_CL_STATS)
1250 Host_Error ("svc_updatestat: %i is invalid", i);
1251 cl.stats[i] = MSG_ReadLong ();
1254 case svc_spawnstaticsound:
1255 CL_ParseStaticSound (false);
1258 case svc_spawnstaticsound2:
1259 CL_ParseStaticSound (true);
1263 cl.cdtrack = MSG_ReadByte ();
1264 cl.looptrack = MSG_ReadByte ();
1265 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1266 CDAudio_Play ((qbyte)cls.forcetrack, true);
1268 CDAudio_Play ((qbyte)cl.cdtrack, true);
1271 case svc_intermission:
1272 cl.intermission = 1;
1273 cl.completed_time = cl.time;
1277 cl.intermission = 2;
1278 cl.completed_time = cl.time;
1279 SCR_CenterPrint (MSG_ReadString ());
1283 cl.intermission = 3;
1284 cl.completed_time = cl.time;
1285 SCR_CenterPrint (MSG_ReadString ());
1288 case svc_sellscreen:
1289 Cmd_ExecuteString ("help", src_command);
1292 SHOWLMP_decodehide();
1295 SHOWLMP_decodeshow();
1298 R_SetSkyBox(MSG_ReadString());
1303 length = (int) ((unsigned short) MSG_ReadShort());
1304 for (i = 0;i < length;i++)
1305 cgamenetbuffer[i] = MSG_ReadByte();
1307 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1311 if (cls.signon == SIGNONS - 1)
1312 { // first update is the final signon stage
1313 cls.signon = SIGNONS;
1316 CL_ReadEntityFrame();
1321 if (entitiesupdated)
1322 CL_EntityUpdateEnd();