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 //FIXME finish this code!
243 #define MAX_STATICLIGHTS 2048
245 #define LIGHTFADE_LMINUSX 0 // light, arghlite, others?
246 #define LIGHTFADE_LDIVX 1
247 #define LIGHTFADE_LDIVX2 2 // hlight
248 #define LIGHTFADE_L 3
249 #define LIGHTFADE_DEFAULT 999999 // light util not yet identified, switched later
253 int fadetype; // one of the LIGHTFADE_ values
256 vec_t radius; // the point at which lighting stops
258 vec_t cone; // if non-zero, it is a spot light
260 vec_t distancescale; // attenuation
261 vec_t lightsubtract; // biasing lighting toward black (hlight feature)
265 staticlight_t staticlight[MAX_STATICLIGHTS];
268 int r_sunlightenabled;
269 vec3_t r_sunlightdirection, r_sunlightcolor;
270 vec3_t r_light_ambientcolor;
272 void CL_ParseEntityLump(char *entdata)
275 char key[128], value[4096];
277 char targetnamebuffer[65536];
278 char *targetname[8192], *target[MAX_STATICLIGHTS], light_target[256];
279 vec3_t targetnameorigin[8192], targetnametemporigin, v;
280 int targets, targetnames, targetnamebufferpos, targetnameorigintofillin;
282 float f1, f2, f3, f4;
283 float ambientlight, ambientcolor[3], sunlight, sunlightdirection[3], sunlightcolor[3];
284 int light_fadetype, light_style, hlight, tyrlite, light_enable;
285 float light_origin[3], light_light, light_distancescale, light_lightcolor[3], light_color[3], light_direction[3], light_cone, light_lightradius;
286 FOG_clear(); // LordHavoc: no fog until set
287 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
288 r_farclip.value = 6144; // LordHavoc: default farclip distance
289 r_sunlightenabled = false;
294 data = COM_Parse(data);
297 if (com_token[0] != '{')
302 ambientcolor[0] = ambientcolor[1] = ambientcolor[2] = 1;
304 sunlightcolor[0] = sunlightcolor[1] = sunlightcolor[2] = 1;
305 sunlightdirection[0] = 0;
306 sunlightdirection[1] = 0;
307 sunlightdirection[2] = -1;
310 targetnamebufferpos = 0;
311 targetnameorigintofillin = -1;
312 targetnametemporigin[0] = 0;
313 targetnametemporigin[1] = 0;
314 targetnametemporigin[2] = 0;
317 data = COM_Parse(data);
320 if (com_token[0] == '}')
321 break; // end of worldspawn
322 if (com_token[0] == '_')
323 strcpy(key, com_token + 1);
325 strcpy(key, com_token);
326 while (key[strlen(key)-1] == ' ') // remove trailing spaces
327 key[strlen(key)-1] = 0;
328 data = COM_Parse(data);
331 strcpy(value, com_token);
332 if (!strcmp("sky", key))
334 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
336 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
338 else if (!strcmp("farclip", key))
340 r_farclip.value = atof(value);
341 if (r_farclip.value < 64)
342 r_farclip.value = 64;
344 else if (!strcmp("fog", key))
345 scanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
346 else if (!strcmp("fog_density", key))
347 fog_density = atof(value);
348 else if (!strcmp("fog_red", key))
349 fog_red = atof(value);
350 else if (!strcmp("fog_green", key))
351 fog_green = atof(value);
352 else if (!strcmp("fog_blue", key))
353 fog_blue = atof(value);
354 else if (!strcmp("wad", key)) // for HalfLife maps
359 for (i = 0;i < 4096;i++)
360 if (value[i] != ';' && value[i] != '\\' && value[i] != '/' && value[i] != ':')
366 // ignore path - the \\ check is for HalfLife... stupid windoze 'programmers'...
367 if (value[i] == '\\' || value[i] == '/' || value[i] == ':')
369 else if (value[i] == ';' || value[i] == 0)
373 strcpy(wadname, "textures/");
374 strcat(wadname, &value[j]);
375 W_LoadTextureWadFile (wadname, false);
384 else if (!strcmp("light", key))
385 ambientlight = atof(value);
386 else if (!strcmp("sunlight", key))
388 sunlight = atof(value);
391 else if (!strcmp("sun_color", key))
393 if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
394 VectorCopy(v, sunlightcolor);
397 else if (!strcmp("sun_mangle", key))
399 if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
400 AngleVectors(v, sunlightdirection, NULL, NULL);
403 else if (!strcmp("origin", key))
405 if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
407 VectorCopy(v, targetnametemporigin);
408 VectorCopy(v, light_origin);
411 else if (!strcmp("targetname", key))
413 if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
415 targetname[targetnames] = targetnamebuffer + targetnamebufferpos;
416 strcpy(targetnamebuffer + targetnamebufferpos, value);
417 targetnamebufferpos += strlen(value) + 1;
418 targetnameorigintofillin = targetnames++;
422 if (targetnameorigintofillin >= 0)
423 VectorCopy(targetnametemporigin, targetnameorigin[targetnameorigintofillin]);
427 r_sunlightenabled = true;
428 VectorScale(sunlightcolor, sunlight, r_sunlightcolor);
429 VectorCopy(sunlightdirection, r_sunlightdirection);
431 VectorScale(ambientcolor, ambientlight, r_light_ambientcolor);
435 data = COM_Parse(data);
438 if (com_token[0] != '{')
441 light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
442 light_color[0] = light_color[1] = light_color[2] = 1.0f;
443 light_direction[0] = light_direction[1] = light_direction[2] = 0.0f;
444 light_cone = -cos(20*M_PI/180);
445 light_distancescale = 1.0f;
446 light_fadetype = LIGHTFADE_DEFAULT; // replaced later when light util is identified
448 light_lightradius = 0;
449 light_enable = false;
450 targetnameorigintofillin = -1;
451 targetnametemporigin[0] = 0;
452 targetnametemporigin[1] = 0;
453 targetnametemporigin[2] = 0;
456 data = COM_Parse(data);
459 if (com_token[0] == '}')
461 if (com_token[0] == '_')
462 strcpy(key, com_token + 1);
464 strcpy(key, com_token);
465 while (key[strlen(key)-1] == ' ') // remove trailing spaces
466 key[strlen(key)-1] = 0;
467 data = COM_Parse(data);
470 strcpy(value, com_token);
471 if (!strcmp("light", key))
473 n = scanf(value, "%f %f %f %f", &f1, &f2, &f3, &f4);
477 // id light, arghlite, tyrlite, others
479 light_lightcolor[0] = light_lightcolor[1] = light_lightcolor[2] = 1.0f;
482 // hlight specific (supports all 3 light formats, but this one is unique to it)
484 light_light = max(f1, max(f2, f3));
485 light_lightcolor[0] = f1 / light_light;
486 light_lightcolor[1] = f2 / light_light;
487 light_lightcolor[2] = f3 / light_light;
491 hlight = true; // unless this is a halflife map, probably hlight
493 light_lightcolor[0] = f1 * (1.0f / 255.0f);
494 light_lightcolor[1] = f1 * (1.0f / 255.0f);
495 light_lightcolor[2] = f1 * (1.0f / 255.0f);
502 else if (!strcmp("color", key))
504 n = scanf(value, "%f %f %f", &f1, &f2, &f3);
511 // n != 3 is an error
513 else if (!strcmp("wait", key))
514 light_distancescale = atof(value);
515 else if (!strcmp("delay", key))
517 light_fadetype = atoi(value);
520 else if (!strcmp("angle", key))
521 light_cone = -cos(atof(value) * M_PI / 360);
522 else if (!strcmp("mangle", key))
524 n = scanf(value, "%f %f %f", &v[0], &v[1], &v[2]);
526 AngleVectors(v, light_direction, NULL, NULL);
527 // n != 3 is an error
530 else if (!strcmp("style", key))
533 if (n >= 0 && n < MAX_LIGHTSTYLES)
536 else if (!strcmp("lightradius", key))
539 light_lightradius = atof(value);
541 else if (!strcmp("classname", key))
542 if (!strncmp(value, "light", 5))
544 else if (!strcmp("origin", key))
546 if (scanf(value, "%f %f %f", &v[0], &v[1], &v[2]) == 3)
547 VectorCopy(v, targetnametemporigin);
549 else if (!strcmp("targetname", key))
551 if ((targetnames < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
553 targetname[targetnames] = targetnamebuffer + targetnamebufferpos;
554 strcpy(targetnamebuffer + targetnamebufferpos, value);
555 targetnamebufferpos += strlen(value) + 1;
556 targetnameorigintofillin = targetnames++;
559 else if (!strcmp("target", key))
560 if (strlen(value) < sizeof(light_target))
561 strcpy(light_target, value);
563 if (targetnameorigintofillin >= 0)
564 VectorCopy(targetnametemporigin, targetnameorigin[targetnameorigintofillin]);
565 if (light_enable && staticlights < MAX_STATICLIGHTS && light_light != 0)
567 VectorCopy(light_origin, staticlight[staticlights].origin);
568 staticlight[staticlights].color[0] = light_light * light_lightcolor[0] * light_color[0];
569 staticlight[staticlights].color[1] = light_light * light_lightcolor[1] * light_color[1];
570 staticlight[staticlights].color[2] = light_light * light_lightcolor[2] * light_color[2];
571 VectorCopy(light_direction, staticlight[staticlights].direction);
572 staticlight[staticlights].cone = light_cone;
573 staticlight[staticlights].distancescale = light_distancescale;
574 staticlight[staticlights].fadetype = light_fadetype;
575 staticlight[staticlights].style = light_style;
576 if (light_target && (targets < 8192) && (strlen(value) + 1 + targetnamebufferpos <= 65536))
578 target[staticlights] = targetnamebuffer + targetnamebufferpos;
579 strcpy(targetnamebuffer + targetnamebufferpos, value);
580 targetnamebufferpos += strlen(value) + 1;
583 target[staticlights] = NULL;
584 staticlight[staticlights].lightsubtract = 0;
585 if (light_lightradius)
587 staticlight[staticlights].fadetype = LIGHTFADE_LDIVX2;
588 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);
594 n = LIGHTFADE_LDIVX2;
596 n = LIGHTFADE_LMINUSX;
598 n = LIGHTFADE_LDIVX2;
600 n = LIGHTFADE_LMINUSX;
601 for (i = 0;i < staticlights;i++)
603 if (staticlight[i].fadetype == LIGHTFADE_DEFAULT)
604 staticlight[i].fadetype = n;
607 for (j = 0;j < targetnames;j++)
609 if (!strcmp(target[i], targetname[j]))
611 VectorSubtract(targetnameorigin[j], staticlight[i].origin, v);
613 VectorCopy(v, staticlight[i].direction);
618 if (staticlight[i].direction[0] == 0 && staticlight[i].direction[1] == 0 && staticlight[i].direction[2] == 0)
619 staticlight[i].cone = 0;
628 void CL_ParseServerInfo (void)
632 int nummodels, numsounds;
633 char model_precache[MAX_MODELS][MAX_QPATH];
634 char sound_precache[MAX_SOUNDS][MAX_QPATH];
636 Con_DPrintf ("Serverinfo packet received.\n");
638 // wipe the client_state_t struct
642 // parse protocol version number
644 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
646 Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
649 Nehahrademcompatibility = false;
651 Nehahrademcompatibility = true;
652 if (cls.demoplayback && demo_nehahra.value)
653 Nehahrademcompatibility = true;
654 dpprotocol = i == DPPROTOCOL_VERSION;
657 cl.maxclients = MSG_ReadByte ();
658 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
660 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
663 cl.scores = Hunk_AllocName (cl.maxclients*sizeof(*cl.scores), "scores");
666 cl.gametype = MSG_ReadByte ();
668 // parse signon message
669 str = MSG_ReadString ();
670 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
672 // seperate the printfs so the server message can have a color
673 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
675 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");
676 Con_Printf ("%c%s\n", 2, str);
680 // first we go through and touch all of the precache data that still
681 // happens to be in the cache, so precaching something else doesn't
682 // needlessly purge it
688 memset (cl.model_precache, 0, sizeof(cl.model_precache));
689 for (nummodels=1 ; ; nummodels++)
691 str = MSG_ReadString ();
694 if (nummodels==MAX_MODELS)
696 Con_Printf ("Server sent too many model precaches\n");
699 if (strlen(str) >= MAX_QPATH)
700 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
701 strcpy (model_precache[nummodels], str);
702 Mod_TouchModel (str);
709 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
710 for (numsounds=1 ; ; numsounds++)
712 str = MSG_ReadString ();
715 if (numsounds==MAX_SOUNDS)
717 Con_Printf ("Server sent too many sound precaches\n");
720 if (strlen(str) >= MAX_QPATH)
721 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
722 strcpy (sound_precache[numsounds], str);
727 // now we try to load everything else until a cache allocation fails
732 for (i=1 ; i<nummodels ; i++)
734 isworldmodel = i == 1; // LordHavoc: first model is the world model
735 cl.model_precache[i] = Mod_ForName (model_precache[i], false);
739 if (cl.model_precache[i] == NULL)
741 Con_Printf("Model %s not found\n", model_precache[i]);
744 CL_KeepaliveMessage ();
749 S_BeginPrecaching ();
750 for (i=1 ; i<numsounds ; i++)
752 cl.sound_precache[i] = S_PrecacheSound (sound_precache[i]);
753 CL_KeepaliveMessage ();
759 cl_entities[0].render.model = cl.worldmodel = cl.model_precache[1];
765 Hunk_Check (); // make sure nothing is hurt
767 noclip_anglehack = false; // noclip is turned off at start
770 void CL_ValidateState(entity_state_t *s)
777 if (s->modelindex >= MAX_MODELS)
778 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
780 // colormap is client index + 1
781 if (s->colormap > cl.maxclients)
782 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
784 model = cl.model_precache[s->modelindex];
785 if (model && s->frame >= model->numframes)
787 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
790 if (model && s->skin >= model->numskins)
792 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
801 Parse an entity update message from the server
802 If an entities model or origin changes from frame to frame, it must be
803 relinked. Other attributes can change without relinking.
806 byte entkill[MAX_EDICTS];
807 int bitprofile[32], bitprofilecount = 0;
808 void CL_ParseUpdate (int bits)
810 int i, num, deltadie;
813 if (cls.signon == SIGNONS - 1)
814 { // first update is the final signon stage
815 cls.signon = SIGNONS;
819 if (bits & U_MOREBITS)
820 bits |= (MSG_ReadByte()<<8);
821 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
823 bits |= MSG_ReadByte() << 16;
824 if (bits & U_EXTEND2)
825 bits |= MSG_ReadByte() << 24;
828 if (bits & U_LONGENTITY)
829 num = (unsigned) MSG_ReadShort ();
831 num = (unsigned) MSG_ReadByte ();
833 if (num >= MAX_EDICTS)
834 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
836 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
838 // mark as visible (no kill)
841 ent = CL_EntityNum (num);
843 for (i = 0;i < 32;i++)
848 ent->state_previous = ent->state_current;
852 if (!ent->state_current.active)
853 deltadie = true; // was not present in previous frame, leave hidden until next full update
856 ent->state_current = ent->state_baseline;
858 ent->state_current.time = cl.mtime[0];
860 ent->state_current.flags = 0;
861 ent->state_current.active = true;
862 if (bits & U_MODEL) ent->state_current.modelindex = (ent->state_current.modelindex & 0xFF00) | MSG_ReadByte();
863 if (bits & U_FRAME) ent->state_current.frame = (ent->state_current.frame & 0xFF00) | MSG_ReadByte();
864 if (bits & U_COLORMAP) ent->state_current.colormap = MSG_ReadByte();
865 if (bits & U_SKIN) ent->state_current.skin = MSG_ReadByte();
866 if (bits & U_EFFECTS) ent->state_current.effects = (ent->state_current.effects & 0xFF00) | MSG_ReadByte();
867 if (bits & U_ORIGIN1) ent->state_current.origin[0] = MSG_ReadCoord();
868 if (bits & U_ANGLE1) ent->state_current.angles[0] = MSG_ReadAngle();
869 if (bits & U_ORIGIN2) ent->state_current.origin[1] = MSG_ReadCoord();
870 if (bits & U_ANGLE2) ent->state_current.angles[1] = MSG_ReadAngle();
871 if (bits & U_ORIGIN3) ent->state_current.origin[2] = MSG_ReadCoord();
872 if (bits & U_ANGLE3) ent->state_current.angles[2] = MSG_ReadAngle();
873 if (bits & U_STEP) ent->state_current.flags |= RENDER_STEP;
874 if (bits & U_ALPHA) ent->state_current.alpha = MSG_ReadByte();
875 if (bits & U_SCALE) ent->state_current.scale = MSG_ReadByte();
876 if (bits & U_EFFECTS2) ent->state_current.effects = (ent->state_current.effects & 0x00FF) | (MSG_ReadByte() << 8);
877 if (bits & U_GLOWSIZE) ent->state_current.glowsize = MSG_ReadByte();
878 if (bits & U_GLOWCOLOR) ent->state_current.glowcolor = MSG_ReadByte();
879 if (bits & U_GLOWTRAIL) ent->state_current.flags |= RENDER_GLOWTRAIL;
880 if (bits & U_COLORMOD) ent->state_current.colormod = MSG_ReadByte();
881 if (bits & U_FRAME2) ent->state_current.frame = (ent->state_current.frame & 0x00FF) | (MSG_ReadByte() << 8);
882 if (bits & U_MODEL2) ent->state_current.modelindex = (ent->state_current.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
883 if (bits & U_VIEWMODEL) ent->state_current.flags |= RENDER_VIEWMODEL;
884 if (bits & U_EXTERIORMODEL) ent->state_current.flags |= RENDER_EXTERIORMODEL;
886 // LordHavoc: to allow playback of the Nehahra movie
887 if (Nehahrademcompatibility && (bits & U_EXTEND1))
889 // LordHavoc: evil format
890 int i = MSG_ReadFloat();
891 int j = MSG_ReadFloat() * 255.0f;
895 ent->state_current.effects |= EF_FULLBRIGHT;
898 ent->state_current.alpha = 0;
899 else if (j == 0 || j >= 255)
900 ent->state_current.alpha = 255;
902 ent->state_current.alpha = j;
908 ent->state_current.active = false;
912 CL_ValidateState(&ent->state_current);
915 if (!ent->state_current.active)
920 Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i %i\n", num, ent->state_previous.modelindex, ent->state_current.modelindex);
922 Con_Printf("CL_ParseUpdate: delta NULL model on %i: %i\n", num, ent->state_previous.modelindex);
927 Con_Printf("CL_ParseUpdate: NULL model on %i: %i %i\n", num, ent->state_baseline.modelindex, ent->state_current.modelindex);
929 Con_Printf("CL_ParseUpdate: NULL model on %i: %i\n", num, ent->state_baseline.modelindex);
936 char *bitprofilenames[32] =
972 void CL_BitProfile_f(void)
975 Con_Printf("bitprofile: %i updates\n");
977 for (i = 0;i < 32;i++)
978 // if (bitprofile[i])
979 Con_Printf("%s: %i %3.2f%%\n", bitprofilenames[i], bitprofile[i], bitprofile[i] * 100.0 / bitprofilecount);
981 for (i = 0;i < 32;i++)
986 void CL_EntityUpdateSetup(void)
988 memset(entkill, 1, MAX_EDICTS);
991 void CL_EntityUpdateEnd(void)
994 for (i = 1;i < MAX_EDICTS;i++)
996 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
1004 void CL_ParseBaseline (entity_t *ent, int large)
1008 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
1009 ent->state_baseline.active = true;
1012 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
1013 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
1017 ent->state_baseline.modelindex = MSG_ReadByte ();
1018 ent->state_baseline.frame = MSG_ReadByte ();
1020 ent->state_baseline.colormap = MSG_ReadByte();
1021 ent->state_baseline.skin = MSG_ReadByte();
1022 for (i = 0;i < 3;i++)
1024 ent->state_baseline.origin[i] = MSG_ReadCoord ();
1025 ent->state_baseline.angles[i] = MSG_ReadAngle ();
1027 ent->state_baseline.alpha = 255;
1028 ent->state_baseline.scale = 16;
1029 ent->state_baseline.glowsize = 0;
1030 ent->state_baseline.glowcolor = 254;
1031 ent->state_baseline.colormod = 255;
1032 ent->state_previous = ent->state_current = ent->state_baseline;
1034 CL_ValidateState(&ent->state_baseline);
1042 Server information pertaining to this client only
1045 void CL_ParseClientdata (int bits)
1050 if (bits & SU_EXTEND1)
1051 bits |= (MSG_ReadByte() << 16);
1052 if (bits & SU_EXTEND2)
1053 bits |= (MSG_ReadByte() << 24);
1055 if (bits & SU_VIEWHEIGHT)
1056 cl.viewheight = MSG_ReadChar ();
1058 cl.viewheight = DEFAULT_VIEWHEIGHT;
1060 if (bits & SU_IDEALPITCH)
1061 cl.idealpitch = MSG_ReadChar ();
1065 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
1066 for (i=0 ; i<3 ; i++)
1068 if (bits & (SU_PUNCH1<<i) )
1071 cl.punchangle[i] = MSG_ReadPreciseAngle();
1073 cl.punchangle[i] = MSG_ReadChar();
1076 cl.punchangle[i] = 0;
1077 if (bits & (SU_PUNCHVEC1<<i))
1078 cl.punchvector[i] = MSG_ReadFloatCoord();
1080 cl.punchvector[i] = 0;
1081 if (bits & (SU_VELOCITY1<<i) )
1082 cl.mvelocity[0][i] = MSG_ReadChar()*16;
1084 cl.mvelocity[0][i] = 0;
1087 i = MSG_ReadLong ();
1089 { // set flash times
1090 for (j=0 ; j<32 ; j++)
1091 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
1092 cl.item_gettime[j] = cl.time;
1096 cl.onground = (bits & SU_ONGROUND) != 0;
1097 cl.inwater = (bits & SU_INWATER) != 0;
1099 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
1100 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
1101 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
1102 cl.stats[STAT_HEALTH] = MSG_ReadShort();
1103 cl.stats[STAT_AMMO] = MSG_ReadByte();
1105 cl.stats[STAT_SHELLS] = MSG_ReadByte();
1106 cl.stats[STAT_NAILS] = MSG_ReadByte();
1107 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
1108 cl.stats[STAT_CELLS] = MSG_ReadByte();
1110 i = MSG_ReadByte ();
1112 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
1113 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
1115 cl.stats[STAT_ACTIVEWEAPON] = i;
1119 =====================
1121 =====================
1123 void CL_ParseStatic (int large)
1127 if (cl.num_statics >= MAX_STATIC_ENTITIES)
1128 Host_Error ("Too many static entities");
1129 ent = &cl_static_entities[cl.num_statics++];
1130 CL_ParseBaseline (ent, large);
1132 // copy it to the current state
1133 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
1134 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
1135 ent->render.framelerp = 0;
1136 // make torchs play out of sync
1137 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
1138 ent->render.colormap = -1; // no special coloring
1139 ent->render.skinnum = ent->state_baseline.skin;
1140 ent->render.effects = ent->state_baseline.effects;
1141 ent->render.alpha = 1;
1142 ent->render.scale = 1;
1143 ent->render.alpha = 1;
1144 ent->render.colormod[0] = ent->render.colormod[1] = ent->render.colormod[2] = 1;
1146 VectorCopy (ent->state_baseline.origin, ent->render.origin);
1147 VectorCopy (ent->state_baseline.angles, ent->render.angles);
1155 void CL_ParseStaticSound (int large)
1158 int sound_num, vol, atten;
1160 MSG_ReadVector(org);
1162 sound_num = (unsigned short) MSG_ReadShort ();
1164 sound_num = MSG_ReadByte ();
1165 vol = MSG_ReadByte ();
1166 atten = MSG_ReadByte ();
1168 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
1171 void CL_ParseEffect (void)
1174 int modelindex, startframe, framecount, framerate;
1176 MSG_ReadVector(org);
1177 modelindex = MSG_ReadByte ();
1178 startframe = MSG_ReadByte ();
1179 framecount = MSG_ReadByte ();
1180 framerate = MSG_ReadByte ();
1182 CL_Effect(org, modelindex, startframe, framecount, framerate);
1185 void CL_ParseEffect2 (void)
1188 int modelindex, startframe, framecount, framerate;
1190 MSG_ReadVector(org);
1191 modelindex = MSG_ReadShort ();
1192 startframe = MSG_ReadShort ();
1193 framecount = MSG_ReadByte ();
1194 framerate = MSG_ReadByte ();
1196 CL_Effect(org, modelindex, startframe, framecount, framerate);
1200 #define SHOWNET(x) if(cl_shownet.value==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1203 =====================
1204 CL_ParseServerMessage
1205 =====================
1207 void CL_ParseServerMessage (void)
1210 int i, entitiesupdated;
1212 char *cmdlogname[32], *temp;
1213 int cmdindex, cmdcount = 0;
1216 // if recording demos, copy the message out
1218 if (cl_shownet.value == 1)
1219 Con_Printf ("%i ",net_message.cursize);
1220 else if (cl_shownet.value == 2)
1221 Con_Printf ("------------------\n");
1223 cl.onground = false; // unless the server says otherwise
1225 // parse the message
1227 MSG_BeginReading ();
1229 entitiesupdated = false;
1230 CL_EntityUpdateSetup();
1235 Host_Error ("CL_ParseServerMessage: Bad server message");
1237 cmd = MSG_ReadByte ();
1241 SHOWNET("END OF MESSAGE");
1242 break; // end of message
1245 cmdindex = cmdcount & 31;
1247 cmdlog[cmdindex] = cmd;
1249 // if the high bit of the command byte is set, it is a fast update
1252 // 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)
1254 cmdlogname[cmdindex] = temp;
1255 SHOWNET("fast update");
1256 CL_ParseUpdate (cmd&127);
1260 SHOWNET(svc_strings[cmd]);
1261 cmdlogname[cmdindex] = svc_strings[cmd];
1262 if (!cmdlogname[cmdindex])
1264 // 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)
1266 cmdlogname[cmdindex] = temp;
1274 char description[32*64], temp[64];
1276 strcpy(description, "packet dump: ");
1280 count = cmdcount - i;
1284 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1285 strcat(description, temp);
1290 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1291 Con_Printf("%s", description);
1292 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1297 // Con_Printf ("svc_nop\n");
1301 // handle old protocols which do not have entity update ranges
1302 entitiesupdated = true;
1303 cl.mtime[1] = cl.mtime[0];
1304 cl.mtime[0] = MSG_ReadFloat ();
1307 case svc_clientdata:
1308 i = MSG_ReadShort ();
1309 CL_ParseClientdata (i);
1313 i = MSG_ReadLong ();
1314 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250)
1315 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION);
1316 Nehahrademcompatibility = false;
1318 Nehahrademcompatibility = true;
1319 if (cls.demoplayback && demo_nehahra.value)
1320 Nehahrademcompatibility = true;
1321 dpprotocol = i == DPPROTOCOL_VERSION;
1324 case svc_disconnect:
1325 Host_EndGame ("Server disconnected\n");
1328 Con_Printf ("%s", MSG_ReadString ());
1331 case svc_centerprint:
1332 SCR_CenterPrint (MSG_ReadString ());
1336 Cbuf_AddText (MSG_ReadString ());
1343 case svc_serverinfo:
1344 CL_ParseServerInfo ();
1345 // vid.recalc_refdef = true; // leave intermission full screen
1349 for (i=0 ; i<3 ; i++)
1350 cl.viewangles[i] = MSG_ReadAngle ();
1354 cl.viewentity = MSG_ReadShort ();
1357 case svc_lightstyle:
1358 i = MSG_ReadByte ();
1359 if (i >= MAX_LIGHTSTYLES)
1360 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1361 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1362 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1363 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1367 CL_ParseStartSoundPacket(false);
1371 CL_ParseStartSoundPacket(true);
1375 i = MSG_ReadShort();
1376 S_StopSound(i>>3, i&7);
1379 case svc_updatename:
1380 i = MSG_ReadByte ();
1381 if (i >= cl.maxclients)
1382 Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD");
1383 strcpy (cl.scores[i].name, MSG_ReadString ());
1386 case svc_updatefrags:
1387 i = MSG_ReadByte ();
1388 if (i >= cl.maxclients)
1389 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD");
1390 cl.scores[i].frags = MSG_ReadShort ();
1393 case svc_updatecolors:
1394 i = MSG_ReadByte ();
1395 if (i >= cl.maxclients)
1396 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD");
1397 cl.scores[i].colors = MSG_ReadByte ();
1401 R_ParseParticleEffect ();
1412 case svc_spawnbaseline:
1413 i = MSG_ReadShort ();
1414 // must use CL_EntityNum() to force cl.num_entities up
1415 CL_ParseBaseline (CL_EntityNum(i), false);
1417 case svc_spawnbaseline2:
1418 i = MSG_ReadShort ();
1419 // must use CL_EntityNum() to force cl.num_entities up
1420 CL_ParseBaseline (CL_EntityNum(i), true);
1422 case svc_spawnstatic:
1423 CL_ParseStatic (false);
1425 case svc_spawnstatic2:
1426 CL_ParseStatic (true);
1428 case svc_temp_entity:
1433 cl.paused = MSG_ReadByte ();
1441 i = MSG_ReadByte ();
1442 if (i <= cls.signon)
1443 Host_Error ("Received signon %i when at %i", i, cls.signon);
1448 case svc_killedmonster:
1449 cl.stats[STAT_MONSTERS]++;
1452 case svc_foundsecret:
1453 cl.stats[STAT_SECRETS]++;
1456 case svc_updatestat:
1457 i = MSG_ReadByte ();
1458 if (i < 0 || i >= MAX_CL_STATS)
1459 Host_Error ("svc_updatestat: %i is invalid", i);
1460 cl.stats[i] = MSG_ReadLong ();
1463 case svc_spawnstaticsound:
1464 CL_ParseStaticSound (false);
1467 case svc_spawnstaticsound2:
1468 CL_ParseStaticSound (true);
1472 cl.cdtrack = MSG_ReadByte ();
1473 cl.looptrack = MSG_ReadByte ();
1474 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1475 CDAudio_Play ((byte)cls.forcetrack, true);
1477 CDAudio_Play ((byte)cl.cdtrack, true);
1480 case svc_intermission:
1481 cl.intermission = 1;
1482 cl.completed_time = cl.time;
1483 // vid.recalc_refdef = true; // go to full screen
1487 cl.intermission = 2;
1488 cl.completed_time = cl.time;
1489 // vid.recalc_refdef = true; // go to full screen
1490 SCR_CenterPrint (MSG_ReadString ());
1494 cl.intermission = 3;
1495 cl.completed_time = cl.time;
1496 // vid.recalc_refdef = true; // go to full screen
1497 SCR_CenterPrint (MSG_ReadString ());
1500 case svc_sellscreen:
1501 Cmd_ExecuteString ("help", src_command);
1504 SHOWLMP_decodehide();
1507 SHOWLMP_decodeshow();
1510 R_SetSkyBox(MSG_ReadString());
1515 if (entitiesupdated)
1516 CL_EntityUpdateEnd();