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
85 "svc_effect", // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate
86 "svc_effect2", // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate
89 //=============================================================================
91 cvar_t demo_nehahra = {0, "demo_nehahra", "0"};
93 void CL_Parse_Init(void)
95 // LordHavoc: added demo_nehahra cvar
96 Cvar_RegisterVariable (&demo_nehahra);
97 if (gamemode == GAME_NEHAHRA)
98 Cvar_SetValue("demo_nehahra", 1);
101 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
102 qboolean dpprotocol; // LordHavoc: whether or not the current network stream is the enhanced DarkPlaces protocol
108 This error checks and tracks the total number of entities
111 entity_t *CL_EntityNum (int num)
114 if (num >= cl.num_entities)
116 if (num >= MAX_EDICTS)
117 Host_Error ("CL_EntityNum: %i is an invalid number",num);
118 cl.num_entities = num;
119 // while (cl.num_entities <= num)
121 // cl_entities[cl.num_entities].colormap = -1; // no special coloring
122 // cl.num_entities++;
126 if (num >= MAX_EDICTS)
127 Host_Error ("CL_EntityNum: %i is an invalid number",num);
129 return &cl_entities[num];
135 CL_ParseStartSoundPacket
138 void CL_ParseStartSoundPacket(int largesoundindex)
148 field_mask = MSG_ReadByte();
150 if (field_mask & SND_VOLUME)
151 volume = MSG_ReadByte ();
153 volume = DEFAULT_SOUND_PACKET_VOLUME;
155 if (field_mask & SND_ATTENUATION)
156 attenuation = MSG_ReadByte () / 64.0;
158 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
160 channel = MSG_ReadShort ();
162 sound_num = (unsigned short) MSG_ReadShort ();
164 sound_num = MSG_ReadByte ();
166 if (sound_num >= MAX_SOUNDS)
167 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
172 if (ent > MAX_EDICTS)
173 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
175 for (i=0 ; i<3 ; i++)
176 pos[i] = MSG_ReadCoord ();
178 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
185 When the client is taking a long time to load stuff, send keepalive messages
186 so the server doesn't disconnect.
189 void CL_KeepaliveMessage (void)
192 static float lastmsg;
198 return; // no need if server is local
199 if (cls.demoplayback)
202 // read messages from server, should just be nops
204 memcpy (olddata, net_message.data, net_message.cursize);
208 ret = CL_GetMessage ();
212 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
214 break; // nothing waiting
216 Host_Error ("CL_KeepaliveMessage: received a message");
219 if (MSG_ReadByte() != svc_nop)
220 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
226 memcpy (net_message.data, olddata, net_message.cursize);
229 time = Sys_DoubleTime ();
230 if (time - lastmsg < 5)
235 Con_Printf ("--> client to server keepalive\n");
237 MSG_WriteByte (&cls.message, clc_nop);
238 NET_SendMessage (cls.netcon, &cls.message);
239 SZ_Clear (&cls.message);
242 void CL_ParseEntityLump(char *entdata)
245 char key[128], value[4096];
246 FOG_clear(); // LordHavoc: no fog until set
247 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
251 data = COM_Parse(data);
254 if (com_token[0] != '{')
258 data = COM_Parse(data);
261 if (com_token[0] == '}')
262 break; // end of worldspawn
263 if (com_token[0] == '_')
264 strcpy(key, com_token + 1);
266 strcpy(key, com_token);
267 while (key[strlen(key)-1] == ' ') // remove trailing spaces
268 key[strlen(key)-1] = 0;
269 data = COM_Parse(data);
272 strcpy(value, com_token);
273 if (!strcmp("sky", key))
275 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
277 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
279 else if (!strcmp("fog", key))
280 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
281 else if (!strcmp("fog_density", key))
282 fog_density = atof(value);
283 else if (!strcmp("fog_red", key))
284 fog_red = atof(value);
285 else if (!strcmp("fog_green", key))
286 fog_green = atof(value);
287 else if (!strcmp("fog_blue", key))
288 fog_blue = atof(value);
293 //this code is going to be removed
295 #define MAX_STATICLIGHTS 2048
297 #define LIGHTFADE_LMINUSX 0 // light, arghlite, others?
298 #define LIGHTFADE_LDIVX 1
299 #define LIGHTFADE_LDIVX2 2 // hlight
300 #define LIGHTFADE_L 3
301 #define LIGHTFADE_DEFAULT 999999 // light util not yet identified, switched later
305 int fadetype; // one of the LIGHTFADE_ values
308 vec_t distancescale; // attenuation
311 vec3_t direction; // direction
312 vec_t cone; // cone cosine, any light cosine outside this range is suddenly black
318 // LIGHTFADE_LDIVX and LIGHTFADE_LDIVX2
319 vec3_t light2; // light * color
320 vec_t lightsubtract; // hlight feature
324 extern staticlight_t staticlight[MAX_STATICLIGHTS];
325 extern int staticlights;
327 extern int r_sunlightenabled;
328 extern vec3_t r_sunlightdirection, r_sunlightcolor;
329 extern vec3_t r_light_ambientcolor;
333 staticlight_t staticlight[MAX_STATICLIGHTS];
336 int r_sunlightenabled;
337 vec3_t r_sunlightdirection, r_sunlightcolor;
338 vec3_t r_light_ambientcolor;
340 void CL_ParseEntityLump(char *entdata)
343 char key[128], value[4096];
344 char targetnamebuffer[65536];
345 char *targetname[8192], *target[MAX_STATICLIGHTS], light_target[256];
346 vec3_t targetnameorigin[8192], v;
347 int targets, targetnames, targetnamebufferpos, targetnameorigintofillin;
349 float f1, f2, f3, f4;
350 float ambientlight, ambientcolor[3], sunlight, sunlightdirection[3], sunlightcolor[3];
351 int light_fadetype, light_style, hlight, tyrlite, light_enable;
352 float light_origin[3], light_light, light_distancescale, light_lightcolor[3], light_color[3], light_direction[3], light_cone, light_lightradius;
353 FOG_clear(); // LordHavoc: no fog until set
354 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
355 r_sunlightenabled = false;
360 data = COM_Parse(data);
363 if (com_token[0] != '{')
368 ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = 1;
370 sunlightcolor[0] = sunlightcolor[1] = sunlightcolor[2] = 1;
371 sunlightdirection[0] = 0;
372 sunlightdirection[1] = 0;
373 sunlightdirection[2] = -1;
376 targetnamebufferpos = 0;
379 data = COM_Parse(data);
382 if (com_token[0] == '}')
383 break; // end of worldspawn
384 if (com_token[0] == '_')
385 strcpy(key, com_token + 1);
387 strcpy(key, com_token);
388 while (key[strlen(key)-1] == ' ') // remove trailing spaces
389 key[strlen(key)-1] = 0;
390 data = COM_Parse(data);
393 strcpy(value, com_token);
394 if (!strcmp("sky", key))
396 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
398 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
400 else if (!strcmp("fog", key))
401 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
402 else if (!strcmp("fog_density", key))
403 fog_density = atof(value);
404 else if (!strcmp("fog_red", key))
405 fog_red = atof(value);
406 else if (!strcmp("fog_green", key))
407 fog_green = atof(value);
408 else if (!strcmp("fog_blue", key))
409 fog_blue = atof(value);
410 else if (!strcmp("light", key))
411 ambientlight = atof(value);
412 else if (!strcmp("sunlight", key))
414 sunlight = atof(value);
417 else if (!strcmp("sun_color", key))
419 if (sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
420 VectorCopy(v, sunlightcolor);
423 else if (!strcmp("sun_mangle", key))
425 if (sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
426 AngleVectors(v, sunlightdirection, NULL, NULL);
433 r_sunlightenabled = true;
434 VectorScale(sunlightcolor, sunlight, r_sunlightcolor);
435 VectorCopy(sunlightdirection, r_sunlightdirection);
437 VectorScale(ambientcolor, ambientlight, r_light_ambientcolor);
441 data = COM_Parse(data);
444 if (com_token[0] != '{')
447 VectorClear(light_origin);
448 light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
449 light_color[0] = light_color[1] = light_color[2] = 1.0f;
450 light_direction[0] = light_direction[1] = light_direction[2] = 0.0f;
451 light_cone = -cos(20*M_PI/180);
452 light_distancescale = 1.0f;
453 light_fadetype = LIGHTFADE_DEFAULT; // replaced later when light util is identified
455 light_lightradius = 0;
456 light_enable = false;
457 targetnameorigintofillin = -1;
460 data = COM_Parse(data);
463 if (com_token[0] == '}')
465 if (com_token[0] == '_')
466 strcpy(key, com_token + 1);
468 strcpy(key, com_token);
469 while (key[strlen(key)-1] == ' ') // remove trailing spaces
470 key[strlen(key)-1] = 0;
471 data = COM_Parse(data);
474 strcpy(value, com_token);
475 if (!strcmp("light", key))
477 n = sscanf(value, "%f %f %f %f", &f1, &f2, &f3, &f4);
481 // id light, arghlite, tyrlite, others
483 light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
486 // hlight specific (supports all 3 light formats, but this one is unique to it)
488 light_light = max(f1, max(f2, f3));
489 light_lightcolor[0] = f1 / light_light;
490 light_lightcolor[1] = f2 / light_light;
491 light_lightcolor[2] = f3 / light_light;
495 hlight = true; // unless this is a halflife map, probably hlight
497 light_lightcolor[0] = f1 * (1.0f / 255.0f);
498 light_lightcolor[1] = f1 * (1.0f / 255.0f);
499 light_lightcolor[2] = f1 * (1.0f / 255.0f);
506 else if (!strcmp("color", key))
508 n = sscanf(value, "%f %f %f", &f1, &f2, &f3);
515 // n != 3 is an error
517 else if (!strcmp("wait", key))
519 light_distancescale = atof(value);
521 else if (!strcmp("delay", key))
523 light_fadetype = atoi(value);
526 else if (!strcmp("angle", key))
528 light_cone = -cos(atof(value) * M_PI / 360);
530 else if (!strcmp("mangle", key))
532 n = sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]);
534 AngleVectors(v, light_direction, NULL, NULL);
535 // n != 3 is an error
538 else if (!strcmp("style", key))
541 if (n >= 0 && n < MAX_LIGHTSTYLES)
544 else if (!strcmp("lightradius", key))
547 light_lightradius = atof(value);
549 else if (!strcmp("classname", key))
551 if (!strncmp(value, "light", 5))
554 else if (!strcmp("origin", key))
556 if (sscanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
557 VectorCopy(v, light_origin);
559 else if (!strcmp("targetname", key))
561 if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
563 targetname[targetnames] = targetnamebuffer + targetnamebufferpos;
564 strcpy(targetnamebuffer + targetnamebufferpos, value);
565 targetnamebufferpos += strlen(value) + 1;
566 targetnameorigintofillin = targetnames++;
569 else if (!strcmp("target", key))
570 if (strlen(value) < sizeof(light_target))
571 strcpy(light_target, value);
573 if (targetnameorigintofillin >= 0)
574 VectorCopy(light_origin, targetnameorigin[targetnameorigintofillin]);
575 if (light_enable && staticlights < MAX_STATICLIGHTS && light_light != 0)
577 if (light_target[0] && (targets < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
579 target[staticlights] = targetnamebuffer + targetnamebufferpos;
580 strcpy(targetnamebuffer + targetnamebufferpos, value);
581 targetnamebufferpos += strlen(value) + 1;
584 target[staticlights] = NULL;
586 staticlight[staticlights].fadetype = light_fadetype;
587 staticlight[staticlights].style = light_style;
588 VectorCopy(light_origin, staticlight[staticlights].origin);
589 staticlight[staticlights].distancescale = light_distancescale;
590 // these are often altered later by the target name linking
591 VectorCopy(light_direction, staticlight[staticlights].direction);
592 staticlight[staticlights].cone = light_cone;
594 staticlight[staticlights].light = light_light;
595 staticlight[staticlights].color[0] = light_lightcolor[0] * light_color[0];
596 staticlight[staticlights].color[1] = light_lightcolor[1] * light_color[1];
597 staticlight[staticlights].color[2] = light_lightcolor[2] * light_color[2];
599 staticlight[staticlights].light2[0] = light_light * light_lightcolor[0] * light_color[0];
600 staticlight[staticlights].light2[1] = light_light * light_lightcolor[1] * light_color[1];
601 staticlight[staticlights].light2[2] = light_light * light_lightcolor[2] * light_color[2];
602 staticlight[staticlights].lightsubtract = 0;
603 if (light_lightradius)
605 staticlight[staticlights].fadetype = LIGHTFADE_LDIVX2;
606 staticlight[staticlights].lightsubtract = max(staticlight[staticlights].color[0], max(staticlight[staticlights].color[1], staticlight[staticlights].color[2])) * 0.5f / (light_lightradius * light_distancescale * light_lightradius * light_distancescale * (1.0f / 65536.0f) + 1.0f);
611 if (cl.worldmodel->ishlbsp)
612 n = LIGHTFADE_LDIVX2;
613 else if (light_hlight.integer)
614 n = LIGHTFADE_LDIVX2;
616 n = LIGHTFADE_LMINUSX;
618 n = LIGHTFADE_LDIVX2;
620 n = LIGHTFADE_LMINUSX;
621 for (i = 0;i < staticlights;i++)
623 if (staticlight[i].fadetype == LIGHTFADE_DEFAULT)
624 staticlight[i].fadetype = n;
627 for (j = 0;j < targetnames;j++)
629 if (!strcmp(target[i], targetname[j]))
631 VectorSubtract(targetnameorigin[j], staticlight[i].origin, v);
633 VectorCopy(v, staticlight[i].direction);
638 if (staticlight[i].direction[0] == 0 && staticlight[i].direction[1] == 0 && staticlight[i].direction[2] == 0)
639 staticlight[i].cone = 0;
645 =====================
648 An svc_signonnum has been received, perform a client side setup
649 =====================
651 static void CL_SignonReply (void)
655 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
660 MSG_WriteByte (&cls.message, clc_stringcmd);
661 MSG_WriteString (&cls.message, "prespawn");
665 MSG_WriteByte (&cls.message, clc_stringcmd);
666 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
668 MSG_WriteByte (&cls.message, clc_stringcmd);
669 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
671 if (cl_pmodel.integer)
673 MSG_WriteByte (&cls.message, clc_stringcmd);
674 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
677 MSG_WriteByte (&cls.message, clc_stringcmd);
678 sprintf (str, "spawn %s", cls.spawnparms);
679 MSG_WriteString (&cls.message, str);
683 MSG_WriteByte (&cls.message, clc_stringcmd);
684 MSG_WriteString (&cls.message, "begin");
688 // SCR_EndLoadingPlaque (); // allow normal screen updates
699 void CL_ParseServerInfo (void)
703 int nummodels, numsounds;
704 char model_precache[MAX_MODELS][MAX_QPATH];
705 char sound_precache[MAX_SOUNDS][MAX_QPATH];
707 Con_DPrintf ("Serverinfo packet received.\n");
709 // wipe the client_state_t struct
713 // parse protocol version number
715 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
717 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
720 Nehahrademcompatibility = false;
722 Nehahrademcompatibility = true;
723 if (cls.demoplayback && demo_nehahra.integer)
724 Nehahrademcompatibility = true;
725 dpprotocol = i == DPPROTOCOL_VERSION;
728 cl.maxclients = MSG_ReadByte ();
729 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
731 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
734 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
737 cl.gametype = MSG_ReadByte ();
739 // parse signon message
740 str = MSG_ReadString ();
741 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
743 // seperate the printfs so the server message can have a color
744 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
746 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");
747 Con_Printf ("%c%s\n", 2, str);
751 // first we go through and touch all of the precache data that still
752 // happens to be in the cache, so precaching something else doesn't
753 // needlessly purge it
756 Mem_CheckSentinelsGlobal();
760 Mem_CheckSentinelsGlobal();
763 memset (cl.model_precache, 0, sizeof(cl.model_precache));
764 for (nummodels=1 ; ; nummodels++)
766 str = MSG_ReadString ();
769 if (nummodels==MAX_MODELS)
771 Con_Printf ("Server sent too many model precaches\n");
774 if (strlen(str) >= MAX_QPATH)
775 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
776 strcpy (model_precache[nummodels], str);
777 Mod_TouchModel (str);
781 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
782 for (numsounds=1 ; ; numsounds++)
784 str = MSG_ReadString ();
787 if (numsounds==MAX_SOUNDS)
789 Con_Printf ("Server sent too many sound precaches\n");
792 if (strlen(str) >= MAX_QPATH)
793 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
794 strcpy (sound_precache[numsounds], str);
798 Mem_CheckSentinelsGlobal();
803 // now we try to load everything else until a cache allocation fails
806 Mem_CheckSentinelsGlobal();
808 for (i=1 ; i<nummodels ; i++)
810 // LordHavoc: i == 1 means the first model is the world model
811 cl.model_precache[i] = Mod_ForName (model_precache[i], false, true, i == 1);
813 if (cl.model_precache[i] == NULL)
815 Con_Printf("Model %s not found\n", model_precache[i]);
818 CL_KeepaliveMessage ();
821 Mem_CheckSentinelsGlobal();
823 S_BeginPrecaching ();
824 for (i=1 ; i<numsounds ; i++)
826 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
827 CL_KeepaliveMessage ();
832 cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
833 cl_entities[0].render.scale = 1;
834 cl_entities[0].render.alpha = 1;
838 Mem_CheckSentinelsGlobal();
840 noclip_anglehack = false; // noclip is turned off at start
843 void CL_ValidateState(entity_state_t *s)
850 if (s->modelindex >= MAX_MODELS)
851 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
853 // colormap is client index + 1
854 if (s->colormap > cl.maxclients)
855 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
857 model = cl.model_precache[s->modelindex];
858 Mod_CheckLoaded(model);
859 if (model && s->frame >= model->numframes)
861 Con_Printf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
864 if (model && s->skin > 0 && s->skin >= model->numskins)
866 Con_Printf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
875 Parse an entity update message from the server
876 If an entities model or origin changes from frame to frame, it must be
877 relinked. Other attributes can change without relinking.
880 byte entkill[MAX_EDICTS];
881 int bitprofile[32], bitprofilecount = 0;
882 void CL_ParseUpdate (int bits)
884 int i, num, deltadie;
888 if (cls.signon == SIGNONS - 1)
889 { // first update is the final signon stage
890 cls.signon = SIGNONS;
894 if (bits & U_MOREBITS)
895 bits |= (MSG_ReadByte()<<8);
896 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
898 bits |= MSG_ReadByte() << 16;
899 if (bits & U_EXTEND2)
900 bits |= MSG_ReadByte() << 24;
903 if (bits & U_LONGENTITY)
904 num = (unsigned) MSG_ReadShort ();
906 num = (unsigned) MSG_ReadByte ();
908 if (num >= MAX_EDICTS)
909 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
911 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
913 // mark as visible (no kill)
916 ent = CL_EntityNum (num);
918 for (i = 0;i < 32;i++)
926 new = ent->state_current;
928 deltadie = true; // was not present in previous frame, leave hidden until next full update
931 new = ent->state_baseline;
933 new.time = cl.mtime[0];
937 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
938 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
939 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
940 if (bits & U_SKIN) new.skin = MSG_ReadByte();
941 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
942 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
943 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
944 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
945 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
946 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
947 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
948 if (bits & U_STEP) new.flags |= RENDER_STEP;
949 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
950 if (bits & U_SCALE) new.scale = MSG_ReadByte();
951 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
952 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
953 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
955 if (bits & U_COLORMOD) {int i = MSG_ReadByte();float r = (((int) i >> 5) & 7) * 1.0 / 7, g = (((int) i >> 2) & 7) * 1.0 / 7, b = ((int) i & 3) * 1.0 / 3;Con_Printf("warning: U_COLORMOD %i (%1.2f %1.2f %1.2f) ignored\n", i, r, g, b);}
957 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
958 if (bits & U_COLORMOD) MSG_ReadByte();
960 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
961 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
962 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
963 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
964 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
966 // LordHavoc: to allow playback of the Nehahra movie
967 if (Nehahrademcompatibility && (bits & U_EXTEND1))
969 // LordHavoc: evil format
970 int i = MSG_ReadFloat();
971 int j = MSG_ReadFloat() * 255.0f;
975 new.effects |= EF_FULLBRIGHT;
979 else if (j == 0 || j >= 255)
991 CL_ValidateState(&new);
993 if (new.flags & RENDER_STEP) // FIXME: rename this flag?
995 // make time identical for memcmp
996 new.time = ent->state_current.time;
997 if (memcmp(&new, &ent->state_current, sizeof(entity_state_t)))
1000 ent->state_previous = ent->state_current;
1001 ent->state_current = new;
1002 // assume 10fps animation
1003 ent->state_previous.time = cl.mtime[0];
1004 ent->state_current.time = cl.mtime[0] + 0.1; //ent->state_previous.time + 0.1;
1009 ent->state_previous = ent->state_current;
1010 ent->state_current = new;
1014 char *bitprofilenames[32] =
1038 "obsolete U_COLORMOD",
1050 void CL_BitProfile_f(void)
1053 Con_Printf("bitprofile: %i updates\n");
1054 if (bitprofilecount)
1055 for (i = 0;i < 32;i++)
1056 // if (bitprofile[i])
1057 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
1059 for (i = 0;i < 32;i++)
1061 bitprofilecount = 0;
1064 void CL_EntityUpdateSetup(void)
1066 memset(entkill, 1, MAX_EDICTS);
1069 void CL_EntityUpdateEnd(void)
1072 for (i = 1;i < MAX_EDICTS;i++)
1074 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
1082 void CL_ParseBaseline (entity_t *ent, int large)
1086 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
1087 ent->state_baseline.active = true;
1090 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
1091 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
1095 ent->state_baseline.modelindex = MSG_ReadByte ();
1096 ent->state_baseline.frame = MSG_ReadByte ();
1098 ent->state_baseline.colormap = MSG_ReadByte();
1099 ent->state_baseline.skin = MSG_ReadByte();
1100 for (i = 0;i < 3;i++)
1102 ent->state_baseline.origin[i] = MSG_ReadCoord ();
1103 ent->state_baseline.angles[i] = MSG_ReadAngle ();
1105 ent->state_baseline.alpha = 255;
1106 ent->state_baseline.scale = 16;
1107 ent->state_baseline.glowsize = 0;
1108 ent->state_baseline.glowcolor = 254;
1109 ent->state_previous = ent->state_current = ent->state_baseline;
1111 CL_ValidateState(&ent->state_baseline);
1119 Server information pertaining to this client only
1122 void CL_ParseClientdata (int bits)
1127 if (bits & SU_EXTEND1)
1128 bits |= (MSG_ReadByte() << 16);
1129 if (bits & SU_EXTEND2)
1130 bits |= (MSG_ReadByte() << 24);
1132 if (bits & SU_VIEWHEIGHT)
1133 cl.viewheight = MSG_ReadChar ();
1135 cl.viewheight = DEFAULT_VIEWHEIGHT;
1137 if (bits & SU_IDEALPITCH)
1138 cl.idealpitch = MSG_ReadChar ();
1142 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
1143 for (i=0 ; i<3 ; i++)
1145 if (bits & (SU_PUNCH1<<i) )
1148 cl.punchangle[i] = MSG_ReadPreciseAngle();
1150 cl.punchangle[i] = MSG_ReadChar();
1153 cl.punchangle[i] = 0;
1154 if (bits & (SU_PUNCHVEC1<<i))
1155 cl.punchvector[i] = MSG_ReadFloatCoord();
1157 cl.punchvector[i] = 0;
1158 if (bits & (SU_VELOCITY1<<i) )
1159 cl.mvelocity[0][i] = MSG_ReadChar()*16;
1161 cl.mvelocity[0][i] = 0;
1164 i = MSG_ReadLong ();
1166 { // set flash times
1167 for (j=0 ; j<32 ; j++)
1168 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
1169 cl.item_gettime[j] = cl.time;
1173 cl.onground = (bits & SU_ONGROUND) != 0;
1174 cl.inwater = (bits & SU_INWATER) != 0;
1176 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
1177 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
1178 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
1179 cl.stats[STAT_HEALTH] = MSG_ReadShort();
1180 cl.stats[STAT_AMMO] = MSG_ReadByte();
1182 cl.stats[STAT_SHELLS] = MSG_ReadByte();
1183 cl.stats[STAT_NAILS] = MSG_ReadByte();
1184 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
1185 cl.stats[STAT_CELLS] = MSG_ReadByte();
1187 i = MSG_ReadByte ();
1189 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
1190 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
1192 cl.stats[STAT_ACTIVEWEAPON] = i;
1196 =====================
1198 =====================
1200 void CL_ParseStatic (int large)
1204 if (cl.num_statics >= MAX_STATIC_ENTITIES)
1205 Host_Error ("Too many static entities");
1206 ent = &cl_static_entities[cl.num_statics++];
1207 CL_ParseBaseline (ent, large);
1209 // copy it to the current state
1210 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
1211 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
1212 ent->render.framelerp = 0;
1213 // make torchs play out of sync
1214 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
1215 ent->render.colormap = -1; // no special coloring
1216 ent->render.skinnum = ent->state_baseline.skin;
1217 ent->render.effects = ent->state_baseline.effects;
1218 ent->render.alpha = 1;
1219 ent->render.scale = 1;
1220 ent->render.alpha = 1;
1222 VectorCopy (ent->state_baseline.origin, ent->render.origin);
1223 VectorCopy (ent->state_baseline.angles, ent->render.angles);
1231 void CL_ParseStaticSound (int large)
1234 int sound_num, vol, atten;
1236 MSG_ReadVector(org);
1238 sound_num = (unsigned short) MSG_ReadShort ();
1240 sound_num = MSG_ReadByte ();
1241 vol = MSG_ReadByte ();
1242 atten = MSG_ReadByte ();
1244 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
1247 void CL_ParseEffect (void)
1250 int modelindex, startframe, framecount, framerate;
1252 MSG_ReadVector(org);
1253 modelindex = MSG_ReadByte ();
1254 startframe = MSG_ReadByte ();
1255 framecount = MSG_ReadByte ();
1256 framerate = MSG_ReadByte ();
1258 CL_Effect(org, modelindex, startframe, framecount, framerate);
1261 void CL_ParseEffect2 (void)
1264 int modelindex, startframe, framecount, framerate;
1266 MSG_ReadVector(org);
1267 modelindex = MSG_ReadShort ();
1268 startframe = MSG_ReadShort ();
1269 framecount = MSG_ReadByte ();
1270 framerate = MSG_ReadByte ();
1272 CL_Effect(org, modelindex, startframe, framecount, framerate);
1276 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1279 =====================
1280 CL_ParseServerMessage
1281 =====================
1283 void CL_ParseServerMessage (void)
1286 int i, entitiesupdated;
1288 char *cmdlogname[32], *temp;
1289 int cmdindex, cmdcount = 0;
1292 // if recording demos, copy the message out
1294 if (cl_shownet.integer == 1)
1295 Con_Printf ("%i ",net_message.cursize);
1296 else if (cl_shownet.integer == 2)
1297 Con_Printf ("------------------\n");
1299 cl.onground = false; // unless the server says otherwise
1301 // parse the message
1303 MSG_BeginReading ();
1305 entitiesupdated = false;
1306 CL_EntityUpdateSetup();
1311 Host_Error ("CL_ParseServerMessage: Bad server message");
1313 cmd = MSG_ReadByte ();
1317 SHOWNET("END OF MESSAGE");
1318 break; // end of message
1321 cmdindex = cmdcount & 31;
1323 cmdlog[cmdindex] = cmd;
1325 // if the high bit of the command byte is set, it is a fast update
1328 // 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)
1330 cmdlogname[cmdindex] = temp;
1331 SHOWNET("fast update");
1332 CL_ParseUpdate (cmd&127);
1336 SHOWNET(svc_strings[cmd]);
1337 cmdlogname[cmdindex] = svc_strings[cmd];
1338 if (!cmdlogname[cmdindex])
1340 // 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)
1342 cmdlogname[cmdindex] = temp;
1350 char description[32*64], temp[64];
1352 strcpy(description, "packet dump: ");
1356 count = cmdcount - i;
1360 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1361 strcat(description, temp);
1366 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1367 Con_Printf("%s", description);
1368 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1373 // Con_Printf ("svc_nop\n");
1377 // handle old protocols which do not have entity update ranges
1378 entitiesupdated = true;
1379 cl.mtime[1] = cl.mtime[0];
1380 cl.mtime[0] = MSG_ReadFloat ();
1383 case svc_clientdata:
1384 i = MSG_ReadShort ();
1385 CL_ParseClientdata (i);
1389 i = MSG_ReadLong ();
1390 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
1391 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
1392 Nehahrademcompatibility = false;
1394 Nehahrademcompatibility = true;
1395 if (cls.demoplayback && demo_nehahra.integer)
1396 Nehahrademcompatibility = true;
1397 dpprotocol = i == DPPROTOCOL_VERSION;
1400 case svc_disconnect:
1401 Host_EndGame ("Server disconnected\n");
1404 Con_Printf ("%s", MSG_ReadString ());
1407 case svc_centerprint:
1408 SCR_CenterPrint (MSG_ReadString ());
1412 Cbuf_AddText (MSG_ReadString ());
1419 case svc_serverinfo:
1420 CL_ParseServerInfo ();
1421 // vid.recalc_refdef = true; // leave intermission full screen
1425 for (i=0 ; i<3 ; i++)
1426 cl.viewangles[i] = MSG_ReadAngle ();
1430 cl.viewentity = MSG_ReadShort ();
1433 case svc_lightstyle:
1434 i = MSG_ReadByte ();
1435 if (i >= MAX_LIGHTSTYLES)
1436 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1437 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1438 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1439 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1443 CL_ParseStartSoundPacket(false);
1447 CL_ParseStartSoundPacket(true);
1451 i = MSG_ReadShort();
1452 S_StopSound(i>>3, i&7);
1455 case svc_updatename:
1456 i = MSG_ReadByte ();
1457 if (i >= cl.maxclients)
1458 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1459 strcpy (cl.scores[i].name, MSG_ReadString ());
1462 case svc_updatefrags:
1463 i = MSG_ReadByte ();
1464 if (i >= cl.maxclients)
1465 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1466 cl.scores[i].frags = MSG_ReadShort ();
1469 case svc_updatecolors:
1470 i = MSG_ReadByte ();
1471 if (i >= cl.maxclients)
1472 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1473 cl.scores[i].colors = MSG_ReadByte ();
1477 CL_ParseParticleEffect ();
1488 case svc_spawnbaseline:
1489 i = MSG_ReadShort ();
1490 // must use CL_EntityNum() to force cl.num_entities up
1491 CL_ParseBaseline (CL_EntityNum(i), false);
1493 case svc_spawnbaseline2:
1494 i = MSG_ReadShort ();
1495 // must use CL_EntityNum() to force cl.num_entities up
1496 CL_ParseBaseline (CL_EntityNum(i), true);
1498 case svc_spawnstatic:
1499 CL_ParseStatic (false);
1501 case svc_spawnstatic2:
1502 CL_ParseStatic (true);
1504 case svc_temp_entity:
1509 cl.paused = MSG_ReadByte ();
1517 i = MSG_ReadByte ();
1518 if (i <= cls.signon)
1519 Host_Error ("Received signon %i when at %i", i, cls.signon);
1524 case svc_killedmonster:
1525 cl.stats[STAT_MONSTERS]++;
1528 case svc_foundsecret:
1529 cl.stats[STAT_SECRETS]++;
1532 case svc_updatestat:
1533 i = MSG_ReadByte ();
1534 if (i < 0 || i >= MAX_CL_STATS)
1535 Host_Error ("svc_updatestat: %i is invalid", i);
1536 cl.stats[i] = MSG_ReadLong ();
1539 case svc_spawnstaticsound:
1540 CL_ParseStaticSound (false);
1543 case svc_spawnstaticsound2:
1544 CL_ParseStaticSound (true);
1548 cl.cdtrack = MSG_ReadByte ();
1549 cl.looptrack = MSG_ReadByte ();
1550 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1551 CDAudio_Play ((byte)cls.forcetrack, true);
1553 CDAudio_Play ((byte)cl.cdtrack, true);
1556 case svc_intermission:
1557 cl.intermission = 1;
1558 cl.completed_time = cl.time;
1559 // vid.recalc_refdef = true; // go to full screen
1563 cl.intermission = 2;
1564 cl.completed_time = cl.time;
1565 // vid.recalc_refdef = true; // go to full screen
1566 SCR_CenterPrint (MSG_ReadString ());
1570 cl.intermission = 3;
1571 cl.completed_time = cl.time;
1572 // vid.recalc_refdef = true; // go to full screen
1573 SCR_CenterPrint (MSG_ReadString ());
1576 case svc_sellscreen:
1577 Cmd_ExecuteString ("help", src_command);
1580 SHOWLMP_decodehide();
1583 SHOWLMP_decodeshow();
1586 R_SetSkyBox(MSG_ReadString());
1591 if (entitiesupdated)
1592 CL_EntityUpdateEnd();