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 qbyte entlife[MAX_EDICTS];
343 void CL_ParseServerInfo (void)
347 int nummodels, numsounds;
348 char model_precache[MAX_MODELS][MAX_QPATH];
349 char sound_precache[MAX_SOUNDS][MAX_QPATH];
352 Con_DPrintf ("Serverinfo packet received.\n");
354 // wipe the client_state_t struct
358 // parse protocol version number
360 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
362 Con_Printf ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
365 Nehahrademcompatibility = false;
367 Nehahrademcompatibility = true;
368 if (cls.demoplayback && demo_nehahra.integer)
369 Nehahrademcompatibility = true;
371 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
375 cl.maxclients = MSG_ReadByte ();
376 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
378 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
381 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
384 cl.gametype = MSG_ReadByte ();
386 // parse signon message
387 str = MSG_ReadString ();
388 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
390 // seperate the printfs so the server message can have a color
391 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
393 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");
394 Con_Printf ("%c%s\n", 2, str);
398 // first we go through and touch all of the precache data that still
399 // happens to be in the cache, so precaching something else doesn't
400 // needlessly purge it
403 Mem_CheckSentinelsGlobal();
408 memset (cl.model_precache, 0, sizeof(cl.model_precache));
409 for (nummodels=1 ; ; nummodels++)
411 str = MSG_ReadString ();
414 if (nummodels==MAX_MODELS)
416 Host_Error ("Server sent too many model precaches\n");
419 if (strlen(str) >= MAX_QPATH)
420 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
421 strcpy (model_precache[nummodels], str);
422 Mod_TouchModel (str);
426 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
427 for (numsounds=1 ; ; numsounds++)
429 str = MSG_ReadString ();
432 if (numsounds==MAX_SOUNDS)
434 Host_Error ("Server sent too many sound precaches\n");
437 if (strlen(str) >= MAX_QPATH)
438 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
439 strcpy (sound_precache[numsounds], str);
446 // now we try to load everything else until a cache allocation fails
449 for (i=1 ; i<nummodels ; i++)
451 // LordHavoc: i == 1 means the first model is the world model
452 cl.model_precache[i] = Mod_ForName (model_precache[i], false, false, i == 1);
454 if (cl.model_precache[i] == NULL)
456 Host_Error("Model %s not found\n", model_precache[i]);
459 CL_KeepaliveMessage ();
462 S_BeginPrecaching ();
463 for (i=1 ; i<numsounds ; i++)
465 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i], true);
466 CL_KeepaliveMessage ();
471 ent = &cl_entities[0];
472 // entire entity array was cleared, so just fill in a few fields
473 ent->state_current.active = true;
474 ent->render.model = cl.worldmodel = cl.model_precache[1];
475 ent->render.scale = 1;
476 ent->render.alpha = 1;
477 VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins);
478 VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs);
479 // clear entlife array
480 memset(entlife, 0, MAX_EDICTS);
488 Mem_CheckSentinelsGlobal();
490 noclip_anglehack = false; // noclip is turned off at start
493 void CL_ValidateState(entity_state_t *s)
500 if (s->modelindex >= MAX_MODELS)
501 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
503 // colormap is client index + 1
504 if (s->colormap > cl.maxclients)
505 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
507 model = cl.model_precache[s->modelindex];
508 Mod_CheckLoaded(model);
509 if (model && s->frame >= model->numframes)
511 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
514 if (model && s->skin > 0 && s->skin >= model->numskins)
516 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
525 Parse an entity update message from the server
526 If an entities model or origin changes from frame to frame, it must be
527 relinked. Other attributes can change without relinking.
530 int bitprofile[32], bitprofilecount = 0;
531 void CL_ParseUpdate (int bits)
537 if (bits & U_MOREBITS)
538 bits |= (MSG_ReadByte()<<8);
539 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
541 bits |= MSG_ReadByte() << 16;
542 if (bits & U_EXTEND2)
543 bits |= MSG_ReadByte() << 24;
546 if (bits & U_LONGENTITY)
547 num = (unsigned) MSG_ReadShort ();
549 num = (unsigned) MSG_ReadByte ();
551 if (num >= MAX_EDICTS)
552 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
554 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
556 // mark as visible (no kill this frame)
559 ent = CL_EntityNum (num);
561 for (i = 0;i < 32;i++)
566 // note: this inherits the 'active' state of the baseline chosen
567 // (state_baseline is always active, state_current may not be active if
568 // the entity was missing in the last frame)
570 new = ent->state_current;
572 new = ent->state_baseline;
574 new.time = cl.mtime[0];
577 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
578 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
579 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
580 if (bits & U_SKIN) new.skin = MSG_ReadByte();
581 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
582 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
583 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
584 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
585 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
586 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
587 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
588 if (bits & U_STEP) new.flags |= RENDER_STEP;
589 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
590 if (bits & U_SCALE) new.scale = MSG_ReadByte();
591 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
592 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
593 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
594 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
595 if (bits & U_COLORMOD) MSG_ReadByte();
596 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
597 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
598 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
599 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
600 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
602 // LordHavoc: to allow playback of the Nehahra movie
603 if (Nehahrademcompatibility && (bits & U_EXTEND1))
605 // LordHavoc: evil format
606 int i = MSG_ReadFloat();
607 int j = MSG_ReadFloat() * 255.0f;
612 new.effects |= EF_FULLBRIGHT;
616 else if (j == 0 || j >= 255)
623 CL_ValidateState(&new);
625 if (new.flags & RENDER_STEP) // FIXME: rename this flag?
627 // make time identical for memcmp
628 new.time = ent->state_current.time;
629 if (memcmp(&new, &ent->state_current, sizeof(entity_state_t)))
631 // set it back to what it should be
632 new.time = cl.mtime[0] + 0.1;
634 ent->state_previous = ent->state_current;
635 ent->state_current = new;
636 // assume 10fps animation
637 //ent->state_previous.time = cl.mtime[0] - 0.1;
642 ent->state_previous = ent->state_current;
643 ent->state_current = new;
647 void CL_ReadEntityFrame(void)
650 entity_frame_t entityframe;
652 EntityFrame_Read(&cl.entitydatabase);
653 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
654 for (i = 0;i < entityframe.numentities;i++)
656 // the entity lives again...
657 entlife[entityframe.entitydata[i].number] = 2;
659 ent = &cl_entities[entityframe.entitydata[i].number];
660 ent->state_previous = ent->state_current;
661 ent->state_current = entityframe.entitydata[i];
662 ent->state_current.time = cl.mtime[0];
664 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
665 VectorCopy(entityframe.eye, cl.viewentoriginnew);
668 char *bitprofilenames[32] =
692 "obsolete U_COLORMOD",
704 void CL_BitProfile_f(void)
707 Con_Printf("bitprofile: %i updates\n");
709 for (i = 0;i < 32;i++)
710 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
712 for (i = 0;i < 32;i++)
717 void CL_EntityUpdateSetup(void)
721 void CL_EntityUpdateEnd(void)
724 // disable entities that disappeared this frame
725 for (i = 1;i < MAX_EDICTS;i++)
727 // clear only the entities that were active last frame but not this
728 // frame, don't waste time clearing all entities (which would cause
734 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
744 void CL_ParseBaseline (entity_t *ent, int large)
748 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
749 ent->state_baseline.active = true;
752 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
753 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
757 ent->state_baseline.modelindex = MSG_ReadByte ();
758 ent->state_baseline.frame = MSG_ReadByte ();
760 ent->state_baseline.colormap = MSG_ReadByte();
761 ent->state_baseline.skin = MSG_ReadByte();
762 for (i = 0;i < 3;i++)
764 ent->state_baseline.origin[i] = MSG_ReadCoord ();
765 ent->state_baseline.angles[i] = MSG_ReadAngle ();
767 ent->state_baseline.alpha = 255;
768 ent->state_baseline.scale = 16;
769 ent->state_baseline.glowsize = 0;
770 ent->state_baseline.glowcolor = 254;
771 ent->state_previous = ent->state_current = ent->state_baseline;
773 CL_ValidateState(&ent->state_baseline);
781 Server information pertaining to this client only
784 void CL_ParseClientdata (int bits)
789 if (bits & SU_EXTEND1)
790 bits |= (MSG_ReadByte() << 16);
791 if (bits & SU_EXTEND2)
792 bits |= (MSG_ReadByte() << 24);
794 if (bits & SU_VIEWHEIGHT)
795 cl.viewheight = MSG_ReadChar ();
797 cl.viewheight = DEFAULT_VIEWHEIGHT;
799 if (bits & SU_IDEALPITCH)
800 cl.idealpitch = MSG_ReadChar ();
804 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
805 for (i=0 ; i<3 ; i++)
807 if (bits & (SU_PUNCH1<<i) )
810 cl.punchangle[i] = MSG_ReadPreciseAngle();
812 cl.punchangle[i] = MSG_ReadChar();
815 cl.punchangle[i] = 0;
816 if (bits & (SU_PUNCHVEC1<<i))
817 cl.punchvector[i] = MSG_ReadCoord();
819 cl.punchvector[i] = 0;
820 if (bits & (SU_VELOCITY1<<i) )
821 cl.mvelocity[0][i] = MSG_ReadChar()*16;
823 cl.mvelocity[0][i] = 0;
829 for (j=0 ; j<32 ; j++)
830 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
831 cl.item_gettime[j] = cl.time;
835 cl.onground = (bits & SU_ONGROUND) != 0;
836 cl.inwater = (bits & SU_INWATER) != 0;
838 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
839 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
840 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
841 cl.stats[STAT_HEALTH] = MSG_ReadShort();
842 cl.stats[STAT_AMMO] = MSG_ReadByte();
844 cl.stats[STAT_SHELLS] = MSG_ReadByte();
845 cl.stats[STAT_NAILS] = MSG_ReadByte();
846 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
847 cl.stats[STAT_CELLS] = MSG_ReadByte();
851 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
852 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
854 cl.stats[STAT_ACTIVEWEAPON] = i;
856 cl.viewzoomold = cl.viewzoomnew; // for interpolation
857 if (bits & SU_VIEWZOOM)
862 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
870 =====================
872 =====================
874 void CL_ParseStatic (int large)
878 if (cl_num_static_entities >= cl_max_static_entities)
879 Host_Error ("Too many static entities");
880 ent = &cl_static_entities[cl_num_static_entities++];
881 CL_ParseBaseline (ent, large);
883 // copy it to the current state
884 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
885 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
886 ent->render.framelerp = 0;
887 // make torchs play out of sync
888 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
889 ent->render.colormap = -1; // no special coloring
890 ent->render.skinnum = ent->state_baseline.skin;
891 ent->render.effects = ent->state_baseline.effects;
892 ent->render.alpha = 1;
893 ent->render.scale = 1;
894 ent->render.alpha = 1;
896 VectorCopy (ent->state_baseline.origin, ent->render.origin);
897 VectorCopy (ent->state_baseline.angles, ent->render.angles);
899 if (ent->render.angles[0] || ent->render.angles[2])
902 VectorAdd(ent->render.origin, ent->render.model->rotatedmins, ent->render.mins);
903 VectorAdd(ent->render.origin, ent->render.model->rotatedmaxs, ent->render.maxs);
905 else if (ent->render.angles[1])
908 VectorAdd(ent->render.origin, ent->render.model->yawmins, ent->render.mins);
909 VectorAdd(ent->render.origin, ent->render.model->yawmaxs, ent->render.maxs);
913 VectorAdd(ent->render.origin, ent->render.model->normalmins, ent->render.mins);
914 VectorAdd(ent->render.origin, ent->render.model->normalmaxs, ent->render.maxs);
917 // This is definitely cheating...
918 if (ent->render.model == NULL)
919 cl_num_static_entities--;
927 void CL_ParseStaticSound (int large)
930 int sound_num, vol, atten;
934 sound_num = (unsigned short) MSG_ReadShort ();
936 sound_num = MSG_ReadByte ();
937 vol = MSG_ReadByte ();
938 atten = MSG_ReadByte ();
940 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
943 void CL_ParseEffect (void)
946 int modelindex, startframe, framecount, framerate;
949 modelindex = MSG_ReadByte ();
950 startframe = MSG_ReadByte ();
951 framecount = MSG_ReadByte ();
952 framerate = MSG_ReadByte ();
954 CL_Effect(org, modelindex, startframe, framecount, framerate);
957 void CL_ParseEffect2 (void)
960 int modelindex, startframe, framecount, framerate;
963 modelindex = MSG_ReadShort ();
964 startframe = MSG_ReadShort ();
965 framecount = MSG_ReadByte ();
966 framerate = MSG_ReadByte ();
968 CL_Effect(org, modelindex, startframe, framecount, framerate);
972 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
974 static qbyte cgamenetbuffer[65536];
977 =====================
978 CL_ParseServerMessage
979 =====================
981 void CL_ParseServerMessage (void)
984 int i, entitiesupdated;
986 char *cmdlogname[32], *temp;
987 int cmdindex, cmdcount = 0;
990 // if recording demos, copy the message out
992 if (cl_shownet.integer == 1)
993 Con_Printf ("%i ",net_message.cursize);
994 else if (cl_shownet.integer == 2)
995 Con_Printf ("------------------\n");
997 cl.onground = false; // unless the server says otherwise
1001 MSG_BeginReading ();
1003 entitiesupdated = false;
1008 Host_Error ("CL_ParseServerMessage: Bad server message");
1010 cmd = MSG_ReadByte ();
1014 SHOWNET("END OF MESSAGE");
1015 break; // end of message
1018 cmdindex = cmdcount & 31;
1020 cmdlog[cmdindex] = cmd;
1022 // if the high bit of the command byte is set, it is a fast update
1025 // 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)
1027 cmdlogname[cmdindex] = temp;
1028 SHOWNET("fast update");
1029 if (cls.signon == SIGNONS - 1)
1031 // first update is the final signon stage
1032 cls.signon = SIGNONS;
1035 CL_ParseUpdate (cmd&127);
1039 SHOWNET(svc_strings[cmd]);
1040 cmdlogname[cmdindex] = svc_strings[cmd];
1041 if (!cmdlogname[cmdindex])
1043 // 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)
1045 cmdlogname[cmdindex] = temp;
1053 char description[32*64], temp[64];
1055 strcpy(description, "packet dump: ");
1059 count = cmdcount - i;
1063 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1064 strcat(description, temp);
1069 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1070 Con_Printf("%s", description);
1071 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1079 if (!entitiesupdated)
1081 // this is a new frame, we'll be seeing entities,
1082 // so prepare for entity updates
1083 CL_EntityUpdateSetup();
1084 entitiesupdated = true;
1086 cl.mtime[1] = cl.mtime[0];
1087 cl.mtime[0] = MSG_ReadFloat ();
1090 case svc_clientdata:
1091 i = MSG_ReadShort ();
1092 CL_ParseClientdata (i);
1096 i = MSG_ReadLong ();
1097 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1098 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1099 Nehahrademcompatibility = false;
1101 Nehahrademcompatibility = true;
1102 if (cls.demoplayback && demo_nehahra.integer)
1103 Nehahrademcompatibility = true;
1105 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1109 case svc_disconnect:
1110 Host_EndGame ("Server disconnected\n");
1113 Con_Printf ("%s", MSG_ReadString ());
1116 case svc_centerprint:
1117 SCR_CenterPrint (MSG_ReadString ());
1121 Cbuf_AddText (MSG_ReadString ());
1128 case svc_serverinfo:
1129 CL_ParseServerInfo ();
1133 for (i=0 ; i<3 ; i++)
1134 cl.viewangles[i] = MSG_ReadAngle ();
1138 cl.viewentity = MSG_ReadShort ();
1139 // LordHavoc: assume first setview recieved is the real player entity
1140 if (!cl.playerentity)
1141 cl.playerentity = cl.viewentity;
1144 case svc_lightstyle:
1145 i = MSG_ReadByte ();
1146 if (i >= MAX_LIGHTSTYLES)
1147 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1148 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1149 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1150 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1154 CL_ParseStartSoundPacket(false);
1158 CL_ParseStartSoundPacket(true);
1162 i = MSG_ReadShort();
1163 S_StopSound(i>>3, i&7);
1166 case svc_updatename:
1167 i = MSG_ReadByte ();
1168 if (i >= cl.maxclients)
1169 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1170 strcpy (cl.scores[i].name, MSG_ReadString ());
1173 case svc_updatefrags:
1174 i = MSG_ReadByte ();
1175 if (i >= cl.maxclients)
1176 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1177 cl.scores[i].frags = MSG_ReadShort ();
1180 case svc_updatecolors:
1181 i = MSG_ReadByte ();
1182 if (i >= cl.maxclients)
1183 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1184 cl.scores[i].colors = MSG_ReadByte ();
1188 CL_ParseParticleEffect ();
1199 case svc_spawnbaseline:
1200 i = MSG_ReadShort ();
1201 // must use CL_EntityNum() to force cl.num_entities up
1202 CL_ParseBaseline (CL_EntityNum(i), false);
1204 case svc_spawnbaseline2:
1205 i = MSG_ReadShort ();
1206 // must use CL_EntityNum() to force cl.num_entities up
1207 CL_ParseBaseline (CL_EntityNum(i), true);
1209 case svc_spawnstatic:
1210 CL_ParseStatic (false);
1212 case svc_spawnstatic2:
1213 CL_ParseStatic (true);
1215 case svc_temp_entity:
1220 cl.paused = MSG_ReadByte ();
1228 i = MSG_ReadByte ();
1229 if (i <= cls.signon)
1230 Host_Error ("Received signon %i when at %i", i, cls.signon);
1235 case svc_killedmonster:
1236 cl.stats[STAT_MONSTERS]++;
1239 case svc_foundsecret:
1240 cl.stats[STAT_SECRETS]++;
1243 case svc_updatestat:
1244 i = MSG_ReadByte ();
1245 if (i < 0 || i >= MAX_CL_STATS)
1246 Host_Error ("svc_updatestat: %i is invalid", i);
1247 cl.stats[i] = MSG_ReadLong ();
1250 case svc_spawnstaticsound:
1251 CL_ParseStaticSound (false);
1254 case svc_spawnstaticsound2:
1255 CL_ParseStaticSound (true);
1259 cl.cdtrack = MSG_ReadByte ();
1260 cl.looptrack = MSG_ReadByte ();
1261 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1262 CDAudio_Play ((qbyte)cls.forcetrack, true);
1264 CDAudio_Play ((qbyte)cl.cdtrack, true);
1267 case svc_intermission:
1268 cl.intermission = 1;
1269 cl.completed_time = cl.time;
1273 cl.intermission = 2;
1274 cl.completed_time = cl.time;
1275 SCR_CenterPrint (MSG_ReadString ());
1279 cl.intermission = 3;
1280 cl.completed_time = cl.time;
1281 SCR_CenterPrint (MSG_ReadString ());
1284 case svc_sellscreen:
1285 Cmd_ExecuteString ("help", src_command);
1288 SHOWLMP_decodehide();
1291 SHOWLMP_decodeshow();
1294 R_SetSkyBox(MSG_ReadString());
1299 length = (int) ((unsigned short) MSG_ReadShort());
1300 for (i = 0;i < length;i++)
1301 cgamenetbuffer[i] = MSG_ReadByte();
1303 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1307 if (cls.signon == SIGNONS - 1)
1309 // first update is the final signon stage
1310 cls.signon = SIGNONS;
1313 CL_ReadEntityFrame();
1318 if (entitiesupdated)
1319 CL_EntityUpdateEnd();