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 qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments
100 int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces
104 CL_ParseStartSoundPacket
107 void CL_ParseStartSoundPacket(int largesoundindex)
117 field_mask = MSG_ReadByte();
119 if (field_mask & SND_VOLUME)
120 volume = MSG_ReadByte ();
122 volume = DEFAULT_SOUND_PACKET_VOLUME;
124 if (field_mask & SND_ATTENUATION)
125 attenuation = MSG_ReadByte () / 64.0;
127 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
129 if (field_mask & SND_LARGEENTITY)
131 ent = (unsigned short) MSG_ReadShort ();
132 channel = MSG_ReadByte ();
136 channel = (unsigned short) MSG_ReadShort ();
141 if (largesoundindex || field_mask & SND_LARGESOUND)
142 sound_num = (unsigned short) MSG_ReadShort ();
144 sound_num = MSG_ReadByte ();
146 if (sound_num >= MAX_SOUNDS)
147 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
150 if (ent >= MAX_EDICTS)
151 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
153 for (i = 0;i < 3;i++)
154 pos[i] = MSG_ReadCoord ();
156 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
163 When the client is taking a long time to load stuff, send keepalive messages
164 so the server doesn't disconnect.
167 void CL_KeepaliveMessage (void)
170 static float lastmsg;
177 return; // no need if server is local
178 if (cls.demoplayback)
181 // read messages from server, should just be nops
183 memcpy (olddata, net_message.data, net_message.cursize);
187 ret = CL_GetMessage ();
191 Host_Error ("CL_KeepaliveMessage: CL_GetMessage failed");
193 break; // nothing waiting
195 Host_Error ("CL_KeepaliveMessage: received a message");
200 Host_Error ("CL_KeepaliveMessage: datagram wasn't a nop");
206 memcpy (net_message.data, olddata, net_message.cursize);
209 time = Sys_DoubleTime ();
210 if (time - lastmsg < 5)
215 Con_Printf ("--> client to server keepalive\n");
217 MSG_WriteByte (&cls.message, clc_nop);
218 NET_SendMessage (cls.netcon, &cls.message);
219 SZ_Clear (&cls.message);
222 void CL_ParseEntityLump(char *entdata)
225 char key[128], value[4096];
226 FOG_clear(); // LordHavoc: no fog until set
227 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
231 if (!COM_ParseToken(&data))
233 if (com_token[0] != '{')
237 if (!COM_ParseToken(&data))
239 if (com_token[0] == '}')
240 break; // end of worldspawn
241 if (com_token[0] == '_')
242 strcpy(key, com_token + 1);
244 strcpy(key, com_token);
245 while (key[strlen(key)-1] == ' ') // remove trailing spaces
246 key[strlen(key)-1] = 0;
247 if (!COM_ParseToken(&data))
249 strcpy(value, com_token);
250 if (!strcmp("sky", key))
252 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
254 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
256 else if (!strcmp("fog", key))
257 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
258 else if (!strcmp("fog_density", key))
259 fog_density = atof(value);
260 else if (!strcmp("fog_red", key))
261 fog_red = atof(value);
262 else if (!strcmp("fog_green", key))
263 fog_green = atof(value);
264 else if (!strcmp("fog_blue", key))
265 fog_blue = atof(value);
270 =====================
273 An svc_signonnum has been received, perform a client side setup
274 =====================
276 static void CL_SignonReply (void)
280 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
285 MSG_WriteByte (&cls.message, clc_stringcmd);
286 MSG_WriteString (&cls.message, "prespawn");
290 MSG_WriteByte (&cls.message, clc_stringcmd);
291 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
293 MSG_WriteByte (&cls.message, clc_stringcmd);
294 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
296 if (cl_pmodel.integer)
298 MSG_WriteByte (&cls.message, clc_stringcmd);
299 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
302 MSG_WriteByte (&cls.message, clc_stringcmd);
303 MSG_WriteString (&cls.message, "spawn");
307 MSG_WriteByte (&cls.message, clc_stringcmd);
308 MSG_WriteString (&cls.message, "begin");
322 qbyte entlife[MAX_EDICTS];
323 // FIXME: this is a lot of memory to be keeping around, this needs to be dynamically allocated and freed
324 static char parse_model_precache[MAX_MODELS][MAX_QPATH];
325 static char parse_sound_precache[MAX_SOUNDS][MAX_QPATH];
326 void CL_ParseServerInfo (void)
330 int nummodels, numsounds;
333 Con_DPrintf ("Serverinfo packet received.\n");
335 // wipe the client_state_t struct
339 // parse protocol version number
341 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
343 Host_Error ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
346 Nehahrademcompatibility = false;
348 Nehahrademcompatibility = true;
349 if (cls.demoplayback && demo_nehahra.integer)
350 Nehahrademcompatibility = true;
352 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
356 cl.maxclients = MSG_ReadByte ();
357 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
359 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
362 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
365 cl.gametype = MSG_ReadByte ();
367 // parse signon message
368 str = MSG_ReadString ();
369 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
371 // seperate the printfs so the server message can have a color
372 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
374 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");
375 Con_Printf ("%c%s\n", 2, str);
378 // check memory integrity
379 Mem_CheckSentinelsGlobal();
381 // disable until we get textures for it
384 memset (cl.model_precache, 0, sizeof(cl.model_precache));
385 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
387 // touch all of the precached models that are still loaded so we can free
388 // anything that isn't needed
390 for (nummodels=1 ; ; nummodels++)
392 CL_KeepaliveMessage ();
393 str = MSG_ReadString ();
396 if (nummodels==MAX_MODELS)
397 Host_Error ("Server sent too many model precaches\n");
398 if (strlen(str) >= MAX_QPATH)
399 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
400 strcpy (parse_model_precache[nummodels], str);
401 Mod_TouchModel (str);
404 // do the same for sounds
405 for (numsounds=1 ; ; numsounds++)
407 CL_KeepaliveMessage ();
408 str = MSG_ReadString ();
411 if (numsounds==MAX_SOUNDS)
412 Host_Error ("Server sent too many sound precaches\n");
413 if (strlen(str) >= MAX_QPATH)
414 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
415 strcpy (parse_sound_precache[numsounds], str);
419 // purge anything that was not touched
422 // now we try to load everything that is new
425 CL_KeepaliveMessage ();
426 cl.model_precache[1] = Mod_ForName (parse_model_precache[1], false, false, true);
427 if (cl.model_precache[1] == NULL)
428 Con_Printf("Map %s not found\n", parse_model_precache[1]);
431 for (i=2 ; i<nummodels ; i++)
433 CL_KeepaliveMessage ();
434 if ((cl.model_precache[i] = Mod_ForName (parse_model_precache[i], false, false, false)) == NULL)
435 Con_Printf("Model %s not found\n", parse_model_precache[i]);
439 S_BeginPrecaching ();
440 for (i=1 ; i<numsounds ; i++)
442 CL_KeepaliveMessage ();
443 cl.sound_precache[i] = S_PrecacheSound (parse_sound_precache[i], true);
448 ent = &cl_entities[0];
449 // entire entity array was cleared, so just fill in a few fields
450 ent->state_current.active = true;
451 ent->render.model = cl.worldmodel = cl.model_precache[1];
452 //ent->render.scale = 1;
453 ent->render.alpha = 1;
454 ent->render.flags = RENDER_SHADOW;
455 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
456 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
457 CL_BoundingBoxForEntity(&ent->render);
458 // clear entlife array
459 memset(entlife, 0, MAX_EDICTS);
466 // noclip is turned off at start
467 noclip_anglehack = false;
469 // check memory integrity
470 Mem_CheckSentinelsGlobal();
473 void CL_ValidateState(entity_state_t *s)
480 if (s->modelindex >= MAX_MODELS)
481 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
483 // colormap is client index + 1
484 if (s->colormap > cl.maxclients)
485 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
487 model = cl.model_precache[s->modelindex];
488 Mod_CheckLoaded(model);
489 if (model && s->frame >= model->numframes)
491 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
494 if (model && s->skin > 0 && s->skin >= model->numskins)
496 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
501 void CL_MoveLerpEntityStates(entity_t *ent)
503 float odelta[3], adelta[3];
504 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
505 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
506 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
508 // we definitely shouldn't lerp
509 ent->persistent.lerpdeltatime = 0;
510 ent->persistent.lerpstarttime = cl.mtime[1];
511 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
512 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
513 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
514 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
516 else if (ent->state_current.flags & RENDER_STEP)
518 // monster interpolation
519 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
521 ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
522 ent->persistent.lerpstarttime = cl.mtime[1];
523 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
524 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
525 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
526 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
532 ent->persistent.lerpstarttime = cl.mtime[1];
533 // no lerp if it's singleplayer
534 if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
535 ent->persistent.lerpdeltatime = 0;
537 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
538 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
539 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
540 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
541 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
549 Parse an entity update message from the server
550 If an entities model or origin changes from frame to frame, it must be
551 relinked. Other attributes can change without relinking.
554 void CL_ParseUpdate (int bits)
560 if (bits & U_MOREBITS)
561 bits |= (MSG_ReadByte()<<8);
562 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
564 bits |= MSG_ReadByte() << 16;
565 if (bits & U_EXTEND2)
566 bits |= MSG_ReadByte() << 24;
569 if (bits & U_LONGENTITY)
570 num = (unsigned) MSG_ReadShort ();
572 num = (unsigned) MSG_ReadByte ();
574 if (num >= MAX_EDICTS)
575 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
577 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
579 ent = cl_entities + num;
581 // note: this inherits the 'active' state of the baseline chosen
582 // (state_baseline is always active, state_current may not be active if
583 // the entity was missing in the last frame)
585 new = ent->state_current;
588 new = ent->state_baseline;
593 new.time = cl.mtime[0];
595 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
596 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
597 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
598 if (bits & U_SKIN) new.skin = MSG_ReadByte();
599 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
600 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
601 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
602 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
603 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
604 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
605 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
606 if (bits & U_STEP) new.flags |= RENDER_STEP;
607 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
608 if (bits & U_SCALE) new.scale = MSG_ReadByte();
609 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
610 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
611 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
612 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
613 if (bits & U_COLORMOD) MSG_ReadByte();
614 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
615 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
616 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
617 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
618 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
620 // LordHavoc: to allow playback of the Nehahra movie
621 if (Nehahrademcompatibility && (bits & U_EXTEND1))
623 // LordHavoc: evil format
624 int i = MSG_ReadFloat();
625 int j = MSG_ReadFloat() * 255.0f;
630 new.effects |= EF_FULLBRIGHT;
634 else if (j == 0 || j >= 255)
641 CL_ValidateState(&new);
643 ent->state_previous = ent->state_current;
644 ent->state_current = new;
645 if (ent->state_current.active)
647 CL_MoveLerpEntityStates(ent);
648 cl_entities_active[ent->state_current.number] = true;
649 // mark as visible (no kill this frame)
650 entlife[ent->state_current.number] = 2;
654 static entity_frame_t entityframe;
655 void CL_ReadEntityFrame(void)
659 EntityFrame_Read(&cl.entitydatabase);
660 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
661 for (i = 0;i < entityframe.numentities;i++)
664 ent = &cl_entities[entityframe.entitydata[i].number];
665 ent->state_previous = ent->state_current;
666 ent->state_current = entityframe.entitydata[i];
667 CL_MoveLerpEntityStates(ent);
668 // the entity lives again...
669 entlife[ent->state_current.number] = 2;
670 cl_entities_active[ent->state_current.number] = true;
674 void CL_EntityUpdateSetup(void)
678 void CL_EntityUpdateEnd(void)
681 // disable entities that disappeared this frame
682 for (i = 1;i < MAX_EDICTS;i++)
684 // clear only the entities that were active last frame but not this
685 // frame, don't waste time clearing all entities (which would cause
691 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
701 void CL_ParseBaseline (entity_t *ent, int large)
705 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
706 ent->state_baseline.active = true;
709 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
710 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
714 ent->state_baseline.modelindex = MSG_ReadByte ();
715 ent->state_baseline.frame = MSG_ReadByte ();
717 ent->state_baseline.colormap = MSG_ReadByte();
718 ent->state_baseline.skin = MSG_ReadByte();
719 for (i = 0;i < 3;i++)
721 ent->state_baseline.origin[i] = MSG_ReadCoord ();
722 ent->state_baseline.angles[i] = MSG_ReadAngle ();
724 ent->state_baseline.alpha = 255;
725 ent->state_baseline.scale = 16;
726 ent->state_baseline.glowsize = 0;
727 ent->state_baseline.glowcolor = 254;
728 ent->state_previous = ent->state_current = ent->state_baseline;
730 CL_ValidateState(&ent->state_baseline);
738 Server information pertaining to this client only
741 void CL_ParseClientdata (int bits)
746 if (bits & SU_EXTEND1)
747 bits |= (MSG_ReadByte() << 16);
748 if (bits & SU_EXTEND2)
749 bits |= (MSG_ReadByte() << 24);
751 if (bits & SU_VIEWHEIGHT)
752 cl.viewheight = MSG_ReadChar ();
754 cl.viewheight = DEFAULT_VIEWHEIGHT;
756 if (bits & SU_IDEALPITCH)
757 cl.idealpitch = MSG_ReadChar ();
761 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
762 for (i=0 ; i<3 ; i++)
764 if (bits & (SU_PUNCH1<<i) )
767 cl.punchangle[i] = MSG_ReadPreciseAngle();
769 cl.punchangle[i] = MSG_ReadChar();
772 cl.punchangle[i] = 0;
773 if (bits & (SU_PUNCHVEC1<<i))
774 cl.punchvector[i] = MSG_ReadCoord();
776 cl.punchvector[i] = 0;
777 if (bits & (SU_VELOCITY1<<i) )
778 cl.mvelocity[0][i] = MSG_ReadChar()*16;
780 cl.mvelocity[0][i] = 0;
786 for (j=0 ; j<32 ; j++)
787 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
788 cl.item_gettime[j] = cl.time;
792 cl.onground = (bits & SU_ONGROUND) != 0;
793 cl.inwater = (bits & SU_INWATER) != 0;
795 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
796 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
797 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
798 cl.stats[STAT_HEALTH] = MSG_ReadShort();
799 cl.stats[STAT_AMMO] = MSG_ReadByte();
801 cl.stats[STAT_SHELLS] = MSG_ReadByte();
802 cl.stats[STAT_NAILS] = MSG_ReadByte();
803 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
804 cl.stats[STAT_CELLS] = MSG_ReadByte();
808 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
809 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
811 cl.stats[STAT_ACTIVEWEAPON] = i;
813 cl.viewzoomold = cl.viewzoomnew; // for interpolation
814 if (bits & SU_VIEWZOOM)
819 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
827 =====================
829 =====================
831 void CL_ParseStatic (int large)
835 if (cl_num_static_entities >= cl_max_static_entities)
836 Host_Error ("Too many static entities");
837 ent = &cl_static_entities[cl_num_static_entities++];
838 CL_ParseBaseline (ent, large);
840 // copy it to the current state
841 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
842 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
843 ent->render.framelerp = 0;
844 // make torchs play out of sync
845 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
846 ent->render.colormap = -1; // no special coloring
847 ent->render.skinnum = ent->state_baseline.skin;
848 ent->render.effects = ent->state_baseline.effects;
849 ent->render.alpha = 1;
850 //ent->render.scale = 1;
852 //VectorCopy (ent->state_baseline.origin, ent->render.origin);
853 //VectorCopy (ent->state_baseline.angles, ent->render.angles);
855 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, ent->state_baseline.origin[0], ent->state_baseline.origin[1], ent->state_baseline.origin[2], ent->state_baseline.angles[0], ent->state_baseline.angles[1], ent->state_baseline.angles[2], 1);
856 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
857 CL_BoundingBoxForEntity(&ent->render);
859 // This is definitely cheating...
860 if (ent->render.model == NULL)
861 cl_num_static_entities--;
869 void CL_ParseStaticSound (int large)
872 int sound_num, vol, atten;
876 sound_num = (unsigned short) MSG_ReadShort ();
878 sound_num = MSG_ReadByte ();
879 vol = MSG_ReadByte ();
880 atten = MSG_ReadByte ();
882 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
885 void CL_ParseEffect (void)
888 int modelindex, startframe, framecount, framerate;
891 modelindex = MSG_ReadByte ();
892 startframe = MSG_ReadByte ();
893 framecount = MSG_ReadByte ();
894 framerate = MSG_ReadByte ();
896 CL_Effect(org, modelindex, startframe, framecount, framerate);
899 void CL_ParseEffect2 (void)
902 int modelindex, startframe, framecount, framerate;
905 modelindex = MSG_ReadShort ();
906 startframe = MSG_ReadShort ();
907 framecount = MSG_ReadByte ();
908 framerate = MSG_ReadByte ();
910 CL_Effect(org, modelindex, startframe, framecount, framerate);
913 model_t *cl_model_bolt = NULL;
914 model_t *cl_model_bolt2 = NULL;
915 model_t *cl_model_bolt3 = NULL;
916 model_t *cl_model_beam = NULL;
918 sfx_t *cl_sfx_wizhit;
919 sfx_t *cl_sfx_knighthit;
924 sfx_t *cl_sfx_r_exp3;
931 void CL_InitTEnts (void)
933 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
934 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
935 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
936 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
937 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
938 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
939 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
942 void CL_ParseBeam (model_t *m, int lightning)
948 ent = MSG_ReadShort ();
949 MSG_ReadVector(start);
952 if (ent >= MAX_EDICTS)
954 Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
958 // override any beam with the same entity
959 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
961 if (b->entity == ent)
964 b->lightning = lightning;
965 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
967 b->endtime = cl.time + 0.2;
968 VectorCopy (start, b->start);
969 VectorCopy (end, b->end);
975 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
977 if (!b->model || b->endtime < cl.time)
980 b->lightning = lightning;
981 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
983 b->endtime = cl.time + 0.2;
984 VectorCopy (start, b->start);
985 VectorCopy (end, b->end);
989 Con_Printf ("beam list overflow!\n");
992 void CL_ParseTempEntity (void)
1000 int colorStart, colorLength, count;
1001 float velspeed, radius;
1004 type = MSG_ReadByte ();
1008 // spike hitting wall
1009 MSG_ReadVector(pos);
1010 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1011 CL_AllocDlight (NULL, pos, 50, 0.25f, 1.00f, 0.25f, 250, 0.2);
1012 CL_RunParticleEffect (pos, vec3_origin, 20, 30);
1013 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
1016 case TE_KNIGHTSPIKE:
1017 // spike hitting wall
1018 MSG_ReadVector(pos);
1019 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1020 CL_AllocDlight (NULL, pos, 50, 1.0f, 0.60f, 0.20f, 250, 0.2);
1021 CL_RunParticleEffect (pos, vec3_origin, 226, 20);
1022 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
1026 // spike hitting wall
1027 MSG_ReadVector(pos);
1028 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1029 // LordHavoc: changed to spark shower
1030 CL_SparkShower(pos, vec3_origin, 15);
1032 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1037 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1039 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1041 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1045 // quad spike hitting wall
1046 MSG_ReadVector(pos);
1047 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1048 // LordHavoc: changed to spark shower
1049 CL_SparkShower(pos, vec3_origin, 15);
1050 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1051 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1053 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1058 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1060 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1062 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1066 // super spike hitting wall
1067 MSG_ReadVector(pos);
1068 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1069 // LordHavoc: changed to dust shower
1070 CL_SparkShower(pos, vec3_origin, 30);
1072 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1077 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1079 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1081 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1084 case TE_SUPERSPIKEQUAD:
1085 // quad super spike hitting wall
1086 MSG_ReadVector(pos);
1087 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1088 // LordHavoc: changed to dust shower
1089 CL_SparkShower(pos, vec3_origin, 30);
1090 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1092 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1097 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1099 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1101 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1104 // LordHavoc: added for improved blood splatters
1107 MSG_ReadVector(pos);
1108 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1109 dir[0] = MSG_ReadChar ();
1110 dir[1] = MSG_ReadChar ();
1111 dir[2] = MSG_ReadChar ();
1112 count = MSG_ReadByte ();
1113 CL_BloodPuff(pos, dir, count);
1117 MSG_ReadVector(pos);
1118 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1119 CL_BloodPuff(pos, vec3_origin, 10);
1123 MSG_ReadVector(pos);
1124 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1125 dir[0] = MSG_ReadChar ();
1126 dir[1] = MSG_ReadChar ();
1127 dir[2] = MSG_ReadChar ();
1128 count = MSG_ReadByte ();
1129 CL_SparkShower(pos, dir, count);
1132 MSG_ReadVector(pos);
1133 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1134 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1137 // LordHavoc: added for improved gore
1138 case TE_BLOODSHOWER:
1140 MSG_ReadVector(pos); // mins
1141 MSG_ReadVector(pos2); // maxs
1142 velspeed = MSG_ReadCoord (); // speed
1143 count = MSG_ReadShort (); // number of particles
1144 CL_BloodShower(pos, pos2, velspeed, count);
1146 case TE_PARTICLECUBE:
1147 // general purpose particle effect
1148 MSG_ReadVector(pos); // mins
1149 MSG_ReadVector(pos2); // maxs
1150 MSG_ReadVector(dir); // dir
1151 count = MSG_ReadShort (); // number of particles
1152 colorStart = MSG_ReadByte (); // color
1153 colorLength = MSG_ReadByte (); // gravity (1 or 0)
1154 velspeed = MSG_ReadCoord (); // randomvel
1155 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1158 case TE_PARTICLERAIN:
1159 // general purpose particle effect
1160 MSG_ReadVector(pos); // mins
1161 MSG_ReadVector(pos2); // maxs
1162 MSG_ReadVector(dir); // dir
1163 count = MSG_ReadShort (); // number of particles
1164 colorStart = MSG_ReadByte (); // color
1165 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1168 case TE_PARTICLESNOW:
1169 // general purpose particle effect
1170 MSG_ReadVector(pos); // mins
1171 MSG_ReadVector(pos2); // maxs
1172 MSG_ReadVector(dir); // dir
1173 count = MSG_ReadShort (); // number of particles
1174 colorStart = MSG_ReadByte (); // color
1175 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1179 // bullet hitting wall
1180 MSG_ReadVector(pos);
1181 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1182 // LordHavoc: changed to dust shower
1183 CL_SparkShower(pos, vec3_origin, 15);
1186 case TE_GUNSHOTQUAD:
1187 // quad bullet hitting wall
1188 MSG_ReadVector(pos);
1189 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1190 CL_SparkShower(pos, vec3_origin, 15);
1191 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1196 MSG_ReadVector(pos);
1197 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1198 CL_ParticleExplosion (pos);
1199 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1200 CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1201 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1204 case TE_EXPLOSIONQUAD:
1205 // quad rocket explosion
1206 MSG_ReadVector(pos);
1207 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1208 CL_ParticleExplosion (pos);
1209 CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1210 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1214 // Nehahra movie colored lighting explosion
1215 MSG_ReadVector(pos);
1216 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1217 CL_ParticleExplosion (pos);
1218 CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1219 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1222 case TE_EXPLOSIONRGB:
1223 // colored lighting explosion
1224 MSG_ReadVector(pos);
1225 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1226 CL_ParticleExplosion (pos);
1227 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1228 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1229 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1230 CL_AllocDlight (NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1231 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1234 case TE_TAREXPLOSION:
1235 // tarbaby explosion
1236 MSG_ReadVector(pos);
1237 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1238 CL_BlobExplosion (pos);
1240 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1241 CL_AllocDlight (NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
1242 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1246 MSG_ReadVector(pos);
1247 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1248 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1251 case TE_CUSTOMFLASH:
1252 MSG_ReadVector(pos);
1253 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1254 radius = MSG_ReadByte() * 8;
1255 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1256 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1257 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1258 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1259 CL_AllocDlight (NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1263 MSG_ReadVector(pos);
1264 MSG_ReadVector(dir);
1265 count = MSG_ReadByte();
1266 CL_Flames(pos, dir, count);
1272 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1273 CL_ParseBeam (cl_model_bolt, true);
1278 if (!cl_model_bolt2)
1279 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1280 CL_ParseBeam (cl_model_bolt2, true);
1285 if (!cl_model_bolt3)
1286 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1287 CL_ParseBeam (cl_model_bolt3, false);
1292 // grappling hook beam
1294 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1295 CL_ParseBeam (cl_model_beam, false);
1299 // LordHavoc: for compatibility with the Nehahra movie...
1300 case TE_LIGHTNING4NEH:
1301 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false), false);
1305 pos[0] = MSG_ReadCoord ();
1306 pos[1] = MSG_ReadCoord ();
1307 pos[2] = MSG_ReadCoord ();
1308 CL_LavaSplash (pos);
1312 pos[0] = MSG_ReadCoord ();
1313 pos[1] = MSG_ReadCoord ();
1314 pos[2] = MSG_ReadCoord ();
1315 CL_AllocDlight (NULL, pos, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f);
1316 // CL_TeleportSplash (pos);
1320 // color mapped explosion
1321 MSG_ReadVector(pos);
1322 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1323 colorStart = MSG_ReadByte ();
1324 colorLength = MSG_ReadByte ();
1325 CL_ParticleExplosion2 (pos, colorStart, colorLength);
1326 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1327 CL_AllocDlight (NULL, pos, 350, tempcolor[0] * (1.0f / 255.0f), tempcolor[1] * (1.0f / 255.0f), tempcolor[2] * (1.0f / 255.0f), 700, 0.5);
1328 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1332 MSG_ReadVector(pos);
1333 MSG_ReadVector(pos2);
1334 MSG_ReadVector(dir);
1335 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1336 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1340 MSG_ReadVector(pos);
1341 MSG_ReadVector(dir);
1342 count = MSG_ReadByte ();
1343 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1344 CL_Tei_Smoke(pos, dir, count);
1347 case TE_TEI_BIGEXPLOSION:
1348 MSG_ReadVector(pos);
1349 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1350 CL_ParticleExplosion (pos);
1351 CL_AllocDlight (NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
1352 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1355 case TE_TEI_PLASMAHIT:
1356 MSG_ReadVector(pos);
1357 MSG_ReadVector(dir);
1358 count = MSG_ReadByte ();
1359 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 5);
1360 CL_Tei_PlasmaHit(pos, dir, count);
1361 CL_AllocDlight (NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
1365 Host_Error ("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1369 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1371 static qbyte cgamenetbuffer[65536];
1374 =====================
1375 CL_ParseServerMessage
1376 =====================
1378 int parsingerror = false;
1379 void CL_ParseServerMessage (void)
1382 int i, entitiesupdated;
1384 char *cmdlogname[32], *temp;
1385 int cmdindex, cmdcount = 0;
1388 // if recording demos, copy the message out
1390 if (cl_shownet.integer == 1)
1391 Con_Printf ("%i ",net_message.cursize);
1392 else if (cl_shownet.integer == 2)
1393 Con_Printf ("------------------\n");
1395 cl.onground = false; // unless the server says otherwise
1397 // parse the message
1399 MSG_BeginReading ();
1401 entitiesupdated = false;
1403 parsingerror = true;
1408 Host_Error ("CL_ParseServerMessage: Bad server message");
1410 cmd = MSG_ReadByte ();
1414 SHOWNET("END OF MESSAGE");
1415 break; // end of message
1418 cmdindex = cmdcount & 31;
1420 cmdlog[cmdindex] = cmd;
1422 // if the high bit of the command byte is set, it is a fast update
1425 // 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)
1427 cmdlogname[cmdindex] = temp;
1428 SHOWNET("fast update");
1429 if (cls.signon == SIGNONS - 1)
1431 // first update is the final signon stage
1432 cls.signon = SIGNONS;
1435 CL_ParseUpdate (cmd&127);
1439 SHOWNET(svc_strings[cmd]);
1440 cmdlogname[cmdindex] = svc_strings[cmd];
1441 if (!cmdlogname[cmdindex])
1443 // 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)
1445 cmdlogname[cmdindex] = temp;
1453 char description[32*64], temp[64];
1455 strcpy(description, "packet dump: ");
1459 count = cmdcount - i;
1463 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1464 strcat(description, temp);
1469 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1470 Con_Printf("%s", description);
1471 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1479 if (!entitiesupdated)
1481 // this is a new frame, we'll be seeing entities,
1482 // so prepare for entity updates
1483 CL_EntityUpdateSetup();
1484 entitiesupdated = true;
1486 cl.mtime[1] = cl.mtime[0];
1487 cl.mtime[0] = MSG_ReadFloat ();
1490 case svc_clientdata:
1491 i = MSG_ReadShort ();
1492 CL_ParseClientdata (i);
1496 i = MSG_ReadLong ();
1497 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1498 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1499 Nehahrademcompatibility = false;
1501 Nehahrademcompatibility = true;
1502 if (cls.demoplayback && demo_nehahra.integer)
1503 Nehahrademcompatibility = true;
1505 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1509 case svc_disconnect:
1510 Host_EndGame ("Server disconnected\n");
1513 Con_Printf ("%s", MSG_ReadString ());
1516 case svc_centerprint:
1517 SCR_CenterPrint (MSG_ReadString ());
1521 Cbuf_AddText (MSG_ReadString ());
1528 case svc_serverinfo:
1529 CL_ParseServerInfo ();
1533 for (i=0 ; i<3 ; i++)
1534 cl.viewangles[i] = MSG_ReadAngle ();
1538 cl.viewentity = MSG_ReadShort ();
1539 // LordHavoc: assume first setview recieved is the real player entity
1540 if (!cl.playerentity)
1541 cl.playerentity = cl.viewentity;
1544 case svc_lightstyle:
1545 i = MSG_ReadByte ();
1546 if (i >= MAX_LIGHTSTYLES)
1547 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1548 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1549 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1550 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1554 CL_ParseStartSoundPacket(false);
1558 CL_ParseStartSoundPacket(true);
1562 i = MSG_ReadShort();
1563 S_StopSound(i>>3, i&7);
1566 case svc_updatename:
1567 i = MSG_ReadByte ();
1568 if (i >= cl.maxclients)
1569 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1570 strcpy (cl.scores[i].name, MSG_ReadString ());
1573 case svc_updatefrags:
1574 i = MSG_ReadByte ();
1575 if (i >= cl.maxclients)
1576 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1577 cl.scores[i].frags = MSG_ReadShort ();
1580 case svc_updatecolors:
1581 i = MSG_ReadByte ();
1582 if (i >= cl.maxclients)
1583 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1584 cl.scores[i].colors = MSG_ReadByte ();
1588 CL_ParseParticleEffect ();
1599 case svc_spawnbaseline:
1600 i = MSG_ReadShort ();
1601 if (i < 0 || i >= MAX_EDICTS)
1602 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1603 CL_ParseBaseline (cl_entities + i, false);
1605 case svc_spawnbaseline2:
1606 i = MSG_ReadShort ();
1607 if (i < 0 || i >= MAX_EDICTS)
1608 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1609 CL_ParseBaseline (cl_entities + i, true);
1611 case svc_spawnstatic:
1612 CL_ParseStatic (false);
1614 case svc_spawnstatic2:
1615 CL_ParseStatic (true);
1617 case svc_temp_entity:
1618 CL_ParseTempEntity ();
1622 cl.paused = MSG_ReadByte ();
1630 i = MSG_ReadByte ();
1631 if (i <= cls.signon)
1632 Host_Error ("Received signon %i when at %i", i, cls.signon);
1637 case svc_killedmonster:
1638 cl.stats[STAT_MONSTERS]++;
1641 case svc_foundsecret:
1642 cl.stats[STAT_SECRETS]++;
1645 case svc_updatestat:
1646 i = MSG_ReadByte ();
1647 if (i < 0 || i >= MAX_CL_STATS)
1648 Host_Error ("svc_updatestat: %i is invalid", i);
1649 cl.stats[i] = MSG_ReadLong ();
1652 case svc_spawnstaticsound:
1653 CL_ParseStaticSound (false);
1656 case svc_spawnstaticsound2:
1657 CL_ParseStaticSound (true);
1661 cl.cdtrack = MSG_ReadByte ();
1662 cl.looptrack = MSG_ReadByte ();
1663 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1664 CDAudio_Play ((qbyte)cls.forcetrack, true);
1666 CDAudio_Play ((qbyte)cl.cdtrack, true);
1669 case svc_intermission:
1670 cl.intermission = 1;
1671 cl.completed_time = cl.time;
1675 cl.intermission = 2;
1676 cl.completed_time = cl.time;
1677 SCR_CenterPrint (MSG_ReadString ());
1681 cl.intermission = 3;
1682 cl.completed_time = cl.time;
1683 SCR_CenterPrint (MSG_ReadString ());
1686 case svc_sellscreen:
1687 Cmd_ExecuteString ("help", src_command);
1690 SHOWLMP_decodehide();
1693 SHOWLMP_decodeshow();
1696 R_SetSkyBox(MSG_ReadString());
1701 length = (int) ((unsigned short) MSG_ReadShort());
1702 for (i = 0;i < length;i++)
1703 cgamenetbuffer[i] = MSG_ReadByte();
1705 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1709 if (cls.signon == SIGNONS - 1)
1711 // first update is the final signon stage
1712 cls.signon = SIGNONS;
1715 CL_ReadEntityFrame();
1720 if (entitiesupdated)
1721 CL_EntityUpdateEnd();
1723 parsingerror = false;
1726 void CL_Parse_DumpPacket(void)
1730 Con_Printf("Packet dump:\n");
1731 SZ_HexDumpToConsole(&net_message);
1732 parsingerror = false;
1735 void CL_Parse_Init(void)
1737 // LordHavoc: added demo_nehahra cvar
1738 Cvar_RegisterVariable (&demo_nehahra);
1739 if (gamemode == GAME_NEHAHRA)
1740 Cvar_SetValue("demo_nehahra", 1);