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);
509 Parse an entity update message from the server
510 If an entities model or origin changes from frame to frame, it must be
511 relinked. Other attributes can change without relinking.
514 int bitprofile[32], bitprofilecount = 0;
515 void CL_ParseUpdate (int bits)
521 if (bits & U_MOREBITS)
522 bits |= (MSG_ReadByte()<<8);
523 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
525 bits |= MSG_ReadByte() << 16;
526 if (bits & U_EXTEND2)
527 bits |= MSG_ReadByte() << 24;
530 if (bits & U_LONGENTITY)
531 num = (unsigned) MSG_ReadShort ();
533 num = (unsigned) MSG_ReadByte ();
535 if (num >= MAX_EDICTS)
536 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
538 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
540 ent = cl_entities + num;
542 for (i = 0;i < 32;i++)
547 // note: this inherits the 'active' state of the baseline chosen
548 // (state_baseline is always active, state_current may not be active if
549 // the entity was missing in the last frame)
551 new = ent->state_current;
553 new = ent->state_baseline;
556 new.time = cl.mtime[0];
558 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
559 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
560 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
561 if (bits & U_SKIN) new.skin = MSG_ReadByte();
562 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
563 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
564 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
565 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
566 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
567 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
568 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
569 if (bits & U_STEP) new.flags |= RENDER_STEP;
570 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
571 if (bits & U_SCALE) new.scale = MSG_ReadByte();
572 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
573 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
574 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
575 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
576 if (bits & U_COLORMOD) MSG_ReadByte();
577 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
578 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
579 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
580 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
581 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
583 // LordHavoc: to allow playback of the Nehahra movie
584 if (Nehahrademcompatibility && (bits & U_EXTEND1))
586 // LordHavoc: evil format
587 int i = MSG_ReadFloat();
588 int j = MSG_ReadFloat() * 255.0f;
593 new.effects |= EF_FULLBRIGHT;
597 else if (j == 0 || j >= 255)
604 CL_ValidateState(&new);
606 if (new.flags & RENDER_STEP) // FIXME: rename this flag?
608 // make time identical for memcmp
609 new.time = ent->state_current.time;
610 if (memcmp(&new, &ent->state_current, sizeof(entity_state_t)))
612 // set it back to what it should be
613 new.time = cl.mtime[0] + 0.1;
615 ent->state_previous = ent->state_current;
616 ent->state_current = new;
617 // assume 10fps animation
618 //ent->state_previous.time = cl.mtime[0] - 0.1;
623 ent->state_previous = ent->state_current;
624 ent->state_current = new;
626 if (ent->state_current.active)
628 cl_entities_active[ent->state_current.number] = true;
629 // mark as visible (no kill this frame)
630 entlife[ent->state_current.number] = 2;
634 void CL_ReadEntityFrame(void)
637 entity_frame_t entityframe;
639 EntityFrame_Read(&cl.entitydatabase);
640 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
641 for (i = 0;i < entityframe.numentities;i++)
644 ent = &cl_entities[entityframe.entitydata[i].number];
645 ent->state_previous = ent->state_current;
646 ent->state_current = entityframe.entitydata[i];
647 ent->state_current.time = cl.mtime[0];
648 // the entity lives again...
649 entlife[ent->state_current.number] = 2;
650 cl_entities_active[ent->state_current.number] = true;
652 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
653 VectorCopy(entityframe.eye, cl.viewentoriginnew);
656 char *bitprofilenames[32] =
680 "obsolete U_COLORMOD",
692 void CL_BitProfile_f(void)
695 Con_Printf("bitprofile: %i updates\n");
697 for (i = 0;i < 32;i++)
698 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
700 for (i = 0;i < 32;i++)
705 void CL_EntityUpdateSetup(void)
709 void CL_EntityUpdateEnd(void)
712 // disable entities that disappeared this frame
713 for (i = 1;i < MAX_EDICTS;i++)
715 // clear only the entities that were active last frame but not this
716 // frame, don't waste time clearing all entities (which would cause
722 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
732 void CL_ParseBaseline (entity_t *ent, int large)
736 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
737 ent->state_baseline.active = true;
740 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
741 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
745 ent->state_baseline.modelindex = MSG_ReadByte ();
746 ent->state_baseline.frame = MSG_ReadByte ();
748 ent->state_baseline.colormap = MSG_ReadByte();
749 ent->state_baseline.skin = MSG_ReadByte();
750 for (i = 0;i < 3;i++)
752 ent->state_baseline.origin[i] = MSG_ReadCoord ();
753 ent->state_baseline.angles[i] = MSG_ReadAngle ();
755 ent->state_baseline.alpha = 255;
756 ent->state_baseline.scale = 16;
757 ent->state_baseline.glowsize = 0;
758 ent->state_baseline.glowcolor = 254;
759 ent->state_previous = ent->state_current = ent->state_baseline;
761 CL_ValidateState(&ent->state_baseline);
769 Server information pertaining to this client only
772 void CL_ParseClientdata (int bits)
777 if (bits & SU_EXTEND1)
778 bits |= (MSG_ReadByte() << 16);
779 if (bits & SU_EXTEND2)
780 bits |= (MSG_ReadByte() << 24);
782 if (bits & SU_VIEWHEIGHT)
783 cl.viewheight = MSG_ReadChar ();
785 cl.viewheight = DEFAULT_VIEWHEIGHT;
787 if (bits & SU_IDEALPITCH)
788 cl.idealpitch = MSG_ReadChar ();
792 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
793 for (i=0 ; i<3 ; i++)
795 if (bits & (SU_PUNCH1<<i) )
798 cl.punchangle[i] = MSG_ReadPreciseAngle();
800 cl.punchangle[i] = MSG_ReadChar();
803 cl.punchangle[i] = 0;
804 if (bits & (SU_PUNCHVEC1<<i))
805 cl.punchvector[i] = MSG_ReadCoord();
807 cl.punchvector[i] = 0;
808 if (bits & (SU_VELOCITY1<<i) )
809 cl.mvelocity[0][i] = MSG_ReadChar()*16;
811 cl.mvelocity[0][i] = 0;
817 for (j=0 ; j<32 ; j++)
818 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
819 cl.item_gettime[j] = cl.time;
823 cl.onground = (bits & SU_ONGROUND) != 0;
824 cl.inwater = (bits & SU_INWATER) != 0;
826 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
827 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
828 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
829 cl.stats[STAT_HEALTH] = MSG_ReadShort();
830 cl.stats[STAT_AMMO] = MSG_ReadByte();
832 cl.stats[STAT_SHELLS] = MSG_ReadByte();
833 cl.stats[STAT_NAILS] = MSG_ReadByte();
834 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
835 cl.stats[STAT_CELLS] = MSG_ReadByte();
839 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
840 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
842 cl.stats[STAT_ACTIVEWEAPON] = i;
844 cl.viewzoomold = cl.viewzoomnew; // for interpolation
845 if (bits & SU_VIEWZOOM)
850 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
858 =====================
860 =====================
862 void CL_ParseStatic (int large)
866 if (cl_num_static_entities >= cl_max_static_entities)
867 Host_Error ("Too many static entities");
868 ent = &cl_static_entities[cl_num_static_entities++];
869 CL_ParseBaseline (ent, large);
871 // copy it to the current state
872 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
873 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
874 ent->render.framelerp = 0;
875 // make torchs play out of sync
876 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
877 ent->render.colormap = -1; // no special coloring
878 ent->render.skinnum = ent->state_baseline.skin;
879 ent->render.effects = ent->state_baseline.effects;
880 ent->render.alpha = 1;
881 ent->render.scale = 1;
882 ent->render.alpha = 1;
884 VectorCopy (ent->state_baseline.origin, ent->render.origin);
885 VectorCopy (ent->state_baseline.angles, ent->render.angles);
887 if (ent->render.angles[0] || ent->render.angles[2])
890 VectorAdd(ent->render.origin, ent->render.model->rotatedmins, ent->render.mins);
891 VectorAdd(ent->render.origin, ent->render.model->rotatedmaxs, ent->render.maxs);
893 else if (ent->render.angles[1])
896 VectorAdd(ent->render.origin, ent->render.model->yawmins, ent->render.mins);
897 VectorAdd(ent->render.origin, ent->render.model->yawmaxs, ent->render.maxs);
901 VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins);
902 VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs);
905 // This is definitely cheating...
906 if (ent->render.model == NULL)
907 cl_num_static_entities--;
915 void CL_ParseStaticSound (int large)
918 int sound_num, vol, atten;
922 sound_num = (unsigned short) MSG_ReadShort ();
924 sound_num = MSG_ReadByte ();
925 vol = MSG_ReadByte ();
926 atten = MSG_ReadByte ();
928 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
931 void CL_ParseEffect (void)
934 int modelindex, startframe, framecount, framerate;
937 modelindex = MSG_ReadByte ();
938 startframe = MSG_ReadByte ();
939 framecount = MSG_ReadByte ();
940 framerate = MSG_ReadByte ();
942 CL_Effect(org, modelindex, startframe, framecount, framerate);
945 void CL_ParseEffect2 (void)
948 int modelindex, startframe, framecount, framerate;
951 modelindex = MSG_ReadShort ();
952 startframe = MSG_ReadShort ();
953 framecount = MSG_ReadByte ();
954 framerate = MSG_ReadByte ();
956 CL_Effect(org, modelindex, startframe, framecount, framerate);
960 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
962 static qbyte cgamenetbuffer[65536];
965 =====================
966 CL_ParseServerMessage
967 =====================
969 void CL_ParseServerMessage (void)
972 int i, entitiesupdated;
974 char *cmdlogname[32], *temp;
975 int cmdindex, cmdcount = 0;
978 // if recording demos, copy the message out
980 if (cl_shownet.integer == 1)
981 Con_Printf ("%i ",net_message.cursize);
982 else if (cl_shownet.integer == 2)
983 Con_Printf ("------------------\n");
985 cl.onground = false; // unless the server says otherwise
991 entitiesupdated = false;
996 Host_Error ("CL_ParseServerMessage: Bad server message");
998 cmd = MSG_ReadByte ();
1002 SHOWNET("END OF MESSAGE");
1003 break; // end of message
1006 cmdindex = cmdcount & 31;
1008 cmdlog[cmdindex] = cmd;
1010 // if the high bit of the command byte is set, it is a fast update
1013 // 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)
1015 cmdlogname[cmdindex] = temp;
1016 SHOWNET("fast update");
1017 if (cls.signon == SIGNONS - 1)
1019 // first update is the final signon stage
1020 cls.signon = SIGNONS;
1023 CL_ParseUpdate (cmd&127);
1027 SHOWNET(svc_strings[cmd]);
1028 cmdlogname[cmdindex] = svc_strings[cmd];
1029 if (!cmdlogname[cmdindex])
1031 // 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)
1033 cmdlogname[cmdindex] = temp;
1041 char description[32*64], temp[64];
1043 strcpy(description, "packet dump: ");
1047 count = cmdcount - i;
1051 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1052 strcat(description, temp);
1057 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1058 Con_Printf("%s", description);
1059 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1067 if (!entitiesupdated)
1069 // this is a new frame, we'll be seeing entities,
1070 // so prepare for entity updates
1071 CL_EntityUpdateSetup();
1072 entitiesupdated = true;
1074 cl.mtime[1] = cl.mtime[0];
1075 cl.mtime[0] = MSG_ReadFloat ();
1078 case svc_clientdata:
1079 i = MSG_ReadShort ();
1080 CL_ParseClientdata (i);
1084 i = MSG_ReadLong ();
1085 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1086 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1087 Nehahrademcompatibility = false;
1089 Nehahrademcompatibility = true;
1090 if (cls.demoplayback && demo_nehahra.integer)
1091 Nehahrademcompatibility = true;
1093 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1097 case svc_disconnect:
1098 Host_EndGame ("Server disconnected\n");
1101 Con_Printf ("%s", MSG_ReadString ());
1104 case svc_centerprint:
1105 SCR_CenterPrint (MSG_ReadString ());
1109 Cbuf_AddText (MSG_ReadString ());
1116 case svc_serverinfo:
1117 CL_ParseServerInfo ();
1121 for (i=0 ; i<3 ; i++)
1122 cl.viewangles[i] = MSG_ReadAngle ();
1126 cl.viewentity = MSG_ReadShort ();
1127 // LordHavoc: assume first setview recieved is the real player entity
1128 if (!cl.playerentity)
1129 cl.playerentity = cl.viewentity;
1132 case svc_lightstyle:
1133 i = MSG_ReadByte ();
1134 if (i >= MAX_LIGHTSTYLES)
1135 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1136 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1137 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1138 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1142 CL_ParseStartSoundPacket(false);
1146 CL_ParseStartSoundPacket(true);
1150 i = MSG_ReadShort();
1151 S_StopSound(i>>3, i&7);
1154 case svc_updatename:
1155 i = MSG_ReadByte ();
1156 if (i >= cl.maxclients)
1157 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1158 strcpy (cl.scores[i].name, MSG_ReadString ());
1161 case svc_updatefrags:
1162 i = MSG_ReadByte ();
1163 if (i >= cl.maxclients)
1164 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1165 cl.scores[i].frags = MSG_ReadShort ();
1168 case svc_updatecolors:
1169 i = MSG_ReadByte ();
1170 if (i >= cl.maxclients)
1171 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1172 cl.scores[i].colors = MSG_ReadByte ();
1176 CL_ParseParticleEffect ();
1187 case svc_spawnbaseline:
1188 i = MSG_ReadShort ();
1189 if (i < 0 || i >= MAX_EDICTS)
1190 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1191 CL_ParseBaseline (cl_entities + i, false);
1193 case svc_spawnbaseline2:
1194 i = MSG_ReadShort ();
1195 if (i < 0 || i >= MAX_EDICTS)
1196 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1197 CL_ParseBaseline (cl_entities + i, true);
1199 case svc_spawnstatic:
1200 CL_ParseStatic (false);
1202 case svc_spawnstatic2:
1203 CL_ParseStatic (true);
1205 case svc_temp_entity:
1210 cl.paused = MSG_ReadByte ();
1218 i = MSG_ReadByte ();
1219 if (i <= cls.signon)
1220 Host_Error ("Received signon %i when at %i", i, cls.signon);
1225 case svc_killedmonster:
1226 cl.stats[STAT_MONSTERS]++;
1229 case svc_foundsecret:
1230 cl.stats[STAT_SECRETS]++;
1233 case svc_updatestat:
1234 i = MSG_ReadByte ();
1235 if (i < 0 || i >= MAX_CL_STATS)
1236 Host_Error ("svc_updatestat: %i is invalid", i);
1237 cl.stats[i] = MSG_ReadLong ();
1240 case svc_spawnstaticsound:
1241 CL_ParseStaticSound (false);
1244 case svc_spawnstaticsound2:
1245 CL_ParseStaticSound (true);
1249 cl.cdtrack = MSG_ReadByte ();
1250 cl.looptrack = MSG_ReadByte ();
1251 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1252 CDAudio_Play ((qbyte)cls.forcetrack, true);
1254 CDAudio_Play ((qbyte)cl.cdtrack, true);
1257 case svc_intermission:
1258 cl.intermission = 1;
1259 cl.completed_time = cl.time;
1263 cl.intermission = 2;
1264 cl.completed_time = cl.time;
1265 SCR_CenterPrint (MSG_ReadString ());
1269 cl.intermission = 3;
1270 cl.completed_time = cl.time;
1271 SCR_CenterPrint (MSG_ReadString ());
1274 case svc_sellscreen:
1275 Cmd_ExecuteString ("help", src_command);
1278 SHOWLMP_decodehide();
1281 SHOWLMP_decodeshow();
1284 R_SetSkyBox(MSG_ReadString());
1289 length = (int) ((unsigned short) MSG_ReadShort());
1290 for (i = 0;i < length;i++)
1291 cgamenetbuffer[i] = MSG_ReadByte();
1293 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1297 if (cls.signon == SIGNONS - 1)
1299 // first update is the final signon stage
1300 cls.signon = SIGNONS;
1303 CL_ReadEntityFrame();
1308 if (entitiesupdated)
1309 CL_EntityUpdateEnd();