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 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
455 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
456 CL_BoundingBoxForEntity(&ent->render);
457 // clear entlife array
458 memset(entlife, 0, MAX_EDICTS);
465 // noclip is turned off at start
466 noclip_anglehack = false;
468 // check memory integrity
469 Mem_CheckSentinelsGlobal();
472 void CL_ValidateState(entity_state_t *s)
479 if (s->modelindex >= MAX_MODELS)
480 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
482 // colormap is client index + 1
483 if (s->colormap > cl.maxclients)
484 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
486 model = cl.model_precache[s->modelindex];
487 Mod_CheckLoaded(model);
488 if (model && s->frame >= model->numframes)
490 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
493 if (model && s->skin > 0 && s->skin >= model->numskins)
495 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
500 void CL_MoveLerpEntityStates(entity_t *ent)
502 float odelta[3], adelta[3];
503 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
504 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
505 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
507 // we definitely shouldn't lerp
508 ent->persistent.lerpdeltatime = 0;
509 ent->persistent.lerpstarttime = cl.mtime[1];
510 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
511 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
512 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
513 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
515 else if (ent->state_current.flags & RENDER_STEP)
517 // monster interpolation
518 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
520 ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
521 ent->persistent.lerpstarttime = cl.mtime[1];
522 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
523 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
524 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
525 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
531 ent->persistent.lerpstarttime = cl.mtime[1];
532 // no lerp if it's singleplayer
533 if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
534 ent->persistent.lerpdeltatime = 0;
536 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
537 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
538 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
539 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
540 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
548 Parse an entity update message from the server
549 If an entities model or origin changes from frame to frame, it must be
550 relinked. Other attributes can change without relinking.
553 void CL_ParseUpdate (int bits)
559 if (bits & U_MOREBITS)
560 bits |= (MSG_ReadByte()<<8);
561 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
563 bits |= MSG_ReadByte() << 16;
564 if (bits & U_EXTEND2)
565 bits |= MSG_ReadByte() << 24;
568 if (bits & U_LONGENTITY)
569 num = (unsigned) MSG_ReadShort ();
571 num = (unsigned) MSG_ReadByte ();
573 if (num >= MAX_EDICTS)
574 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
576 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
578 ent = cl_entities + num;
580 // note: this inherits the 'active' state of the baseline chosen
581 // (state_baseline is always active, state_current may not be active if
582 // the entity was missing in the last frame)
584 new = ent->state_current;
587 new = ent->state_baseline;
592 new.time = cl.mtime[0];
594 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
595 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
596 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
597 if (bits & U_SKIN) new.skin = MSG_ReadByte();
598 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
599 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
600 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
601 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
602 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
603 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
604 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
605 if (bits & U_STEP) new.flags |= RENDER_STEP;
606 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
607 if (bits & U_SCALE) new.scale = MSG_ReadByte();
608 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
609 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
610 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
611 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
612 if (bits & U_COLORMOD) MSG_ReadByte();
613 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
614 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
615 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
616 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
617 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
619 // LordHavoc: to allow playback of the Nehahra movie
620 if (Nehahrademcompatibility && (bits & U_EXTEND1))
622 // LordHavoc: evil format
623 int i = MSG_ReadFloat();
624 int j = MSG_ReadFloat() * 255.0f;
629 new.effects |= EF_FULLBRIGHT;
633 else if (j == 0 || j >= 255)
640 CL_ValidateState(&new);
642 ent->state_previous = ent->state_current;
643 ent->state_current = new;
644 if (ent->state_current.active)
646 CL_MoveLerpEntityStates(ent);
647 cl_entities_active[ent->state_current.number] = true;
648 // mark as visible (no kill this frame)
649 entlife[ent->state_current.number] = 2;
653 static entity_frame_t entityframe;
654 void CL_ReadEntityFrame(void)
658 EntityFrame_Read(&cl.entitydatabase);
659 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
660 for (i = 0;i < entityframe.numentities;i++)
663 ent = &cl_entities[entityframe.entitydata[i].number];
664 ent->state_previous = ent->state_current;
665 ent->state_current = entityframe.entitydata[i];
666 CL_MoveLerpEntityStates(ent);
667 // the entity lives again...
668 entlife[ent->state_current.number] = 2;
669 cl_entities_active[ent->state_current.number] = true;
671 VectorCopy(cl.viewentoriginnew, cl.viewentoriginold);
672 VectorCopy(entityframe.eye, cl.viewentoriginnew);
675 void CL_EntityUpdateSetup(void)
679 void CL_EntityUpdateEnd(void)
682 // disable entities that disappeared this frame
683 for (i = 1;i < MAX_EDICTS;i++)
685 // clear only the entities that were active last frame but not this
686 // frame, don't waste time clearing all entities (which would cause
692 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
702 void CL_ParseBaseline (entity_t *ent, int large)
706 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
707 ent->state_baseline.active = true;
710 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
711 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
715 ent->state_baseline.modelindex = MSG_ReadByte ();
716 ent->state_baseline.frame = MSG_ReadByte ();
718 ent->state_baseline.colormap = MSG_ReadByte();
719 ent->state_baseline.skin = MSG_ReadByte();
720 for (i = 0;i < 3;i++)
722 ent->state_baseline.origin[i] = MSG_ReadCoord ();
723 ent->state_baseline.angles[i] = MSG_ReadAngle ();
725 ent->state_baseline.alpha = 255;
726 ent->state_baseline.scale = 16;
727 ent->state_baseline.glowsize = 0;
728 ent->state_baseline.glowcolor = 254;
729 ent->state_previous = ent->state_current = ent->state_baseline;
731 CL_ValidateState(&ent->state_baseline);
739 Server information pertaining to this client only
742 void CL_ParseClientdata (int bits)
747 if (bits & SU_EXTEND1)
748 bits |= (MSG_ReadByte() << 16);
749 if (bits & SU_EXTEND2)
750 bits |= (MSG_ReadByte() << 24);
752 if (bits & SU_VIEWHEIGHT)
753 cl.viewheight = MSG_ReadChar ();
755 cl.viewheight = DEFAULT_VIEWHEIGHT;
757 if (bits & SU_IDEALPITCH)
758 cl.idealpitch = MSG_ReadChar ();
762 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
763 for (i=0 ; i<3 ; i++)
765 if (bits & (SU_PUNCH1<<i) )
768 cl.punchangle[i] = MSG_ReadPreciseAngle();
770 cl.punchangle[i] = MSG_ReadChar();
773 cl.punchangle[i] = 0;
774 if (bits & (SU_PUNCHVEC1<<i))
775 cl.punchvector[i] = MSG_ReadCoord();
777 cl.punchvector[i] = 0;
778 if (bits & (SU_VELOCITY1<<i) )
779 cl.mvelocity[0][i] = MSG_ReadChar()*16;
781 cl.mvelocity[0][i] = 0;
787 for (j=0 ; j<32 ; j++)
788 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
789 cl.item_gettime[j] = cl.time;
793 cl.onground = (bits & SU_ONGROUND) != 0;
794 cl.inwater = (bits & SU_INWATER) != 0;
796 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
797 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
798 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
799 cl.stats[STAT_HEALTH] = MSG_ReadShort();
800 cl.stats[STAT_AMMO] = MSG_ReadByte();
802 cl.stats[STAT_SHELLS] = MSG_ReadByte();
803 cl.stats[STAT_NAILS] = MSG_ReadByte();
804 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
805 cl.stats[STAT_CELLS] = MSG_ReadByte();
809 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
810 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
812 cl.stats[STAT_ACTIVEWEAPON] = i;
814 cl.viewzoomold = cl.viewzoomnew; // for interpolation
815 if (bits & SU_VIEWZOOM)
820 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
828 =====================
830 =====================
832 void CL_ParseStatic (int large)
836 if (cl_num_static_entities >= cl_max_static_entities)
837 Host_Error ("Too many static entities");
838 ent = &cl_static_entities[cl_num_static_entities++];
839 CL_ParseBaseline (ent, large);
841 // copy it to the current state
842 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
843 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
844 ent->render.framelerp = 0;
845 // make torchs play out of sync
846 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
847 ent->render.colormap = -1; // no special coloring
848 ent->render.skinnum = ent->state_baseline.skin;
849 ent->render.effects = ent->state_baseline.effects;
850 ent->render.alpha = 1;
851 //ent->render.scale = 1;
853 //VectorCopy (ent->state_baseline.origin, ent->render.origin);
854 //VectorCopy (ent->state_baseline.angles, ent->render.angles);
856 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);
857 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
858 CL_BoundingBoxForEntity(&ent->render);
860 // This is definitely cheating...
861 if (ent->render.model == NULL)
862 cl_num_static_entities--;
870 void CL_ParseStaticSound (int large)
873 int sound_num, vol, atten;
877 sound_num = (unsigned short) MSG_ReadShort ();
879 sound_num = MSG_ReadByte ();
880 vol = MSG_ReadByte ();
881 atten = MSG_ReadByte ();
883 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
886 void CL_ParseEffect (void)
889 int modelindex, startframe, framecount, framerate;
892 modelindex = MSG_ReadByte ();
893 startframe = MSG_ReadByte ();
894 framecount = MSG_ReadByte ();
895 framerate = MSG_ReadByte ();
897 CL_Effect(org, modelindex, startframe, framecount, framerate);
900 void CL_ParseEffect2 (void)
903 int modelindex, startframe, framecount, framerate;
906 modelindex = MSG_ReadShort ();
907 startframe = MSG_ReadShort ();
908 framecount = MSG_ReadByte ();
909 framerate = MSG_ReadByte ();
911 CL_Effect(org, modelindex, startframe, framecount, framerate);
914 model_t *cl_model_bolt = NULL;
915 model_t *cl_model_bolt2 = NULL;
916 model_t *cl_model_bolt3 = NULL;
917 model_t *cl_model_beam = NULL;
919 sfx_t *cl_sfx_wizhit;
920 sfx_t *cl_sfx_knighthit;
925 sfx_t *cl_sfx_r_exp3;
932 void CL_InitTEnts (void)
934 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
935 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
936 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
937 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
938 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
939 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
940 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
943 void CL_ParseBeam (model_t *m, int lightning)
949 ent = MSG_ReadShort ();
950 MSG_ReadVector(start);
953 if (ent >= MAX_EDICTS)
955 Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
959 // override any beam with the same entity
960 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
962 if (b->entity == ent)
965 b->lightning = lightning;
966 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
968 b->endtime = cl.time + 0.2;
969 VectorCopy (start, b->start);
970 VectorCopy (end, b->end);
976 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
978 if (!b->model || b->endtime < cl.time)
981 b->lightning = lightning;
982 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
984 b->endtime = cl.time + 0.2;
985 VectorCopy (start, b->start);
986 VectorCopy (end, b->end);
990 Con_Printf ("beam list overflow!\n");
993 void CL_ParseTempEntity (void)
1001 int colorStart, colorLength, count;
1002 float velspeed, radius;
1005 type = MSG_ReadByte ();
1009 // spike hitting wall
1010 MSG_ReadVector(pos);
1011 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1012 CL_AllocDlight (NULL, pos, 50, 0.25f, 1.00f, 0.25f, 250, 0.2);
1013 CL_RunParticleEffect (pos, vec3_origin, 20, 30);
1014 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
1017 case TE_KNIGHTSPIKE:
1018 // spike hitting wall
1019 MSG_ReadVector(pos);
1020 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1021 CL_AllocDlight (NULL, pos, 50, 1.0f, 0.60f, 0.20f, 250, 0.2);
1022 CL_RunParticleEffect (pos, vec3_origin, 226, 20);
1023 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
1027 // spike hitting wall
1028 MSG_ReadVector(pos);
1029 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1030 // LordHavoc: changed to spark shower
1031 CL_SparkShower(pos, vec3_origin, 15);
1033 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1038 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1040 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1042 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1046 // quad spike hitting wall
1047 MSG_ReadVector(pos);
1048 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1049 // LordHavoc: changed to spark shower
1050 CL_SparkShower(pos, vec3_origin, 15);
1051 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1052 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1054 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1059 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1061 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1063 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1067 // super spike hitting wall
1068 MSG_ReadVector(pos);
1069 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1070 // LordHavoc: changed to dust shower
1071 CL_SparkShower(pos, vec3_origin, 30);
1073 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1078 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1080 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1082 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1085 case TE_SUPERSPIKEQUAD:
1086 // quad super spike hitting wall
1087 MSG_ReadVector(pos);
1088 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1089 // LordHavoc: changed to dust shower
1090 CL_SparkShower(pos, vec3_origin, 30);
1091 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1093 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1098 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1100 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1102 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1105 // LordHavoc: added for improved blood splatters
1108 MSG_ReadVector(pos);
1109 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1110 dir[0] = MSG_ReadChar ();
1111 dir[1] = MSG_ReadChar ();
1112 dir[2] = MSG_ReadChar ();
1113 count = MSG_ReadByte ();
1114 CL_BloodPuff(pos, dir, count);
1118 MSG_ReadVector(pos);
1119 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1120 CL_BloodPuff(pos, vec3_origin, 10);
1124 MSG_ReadVector(pos);
1125 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1126 dir[0] = MSG_ReadChar ();
1127 dir[1] = MSG_ReadChar ();
1128 dir[2] = MSG_ReadChar ();
1129 count = MSG_ReadByte ();
1130 CL_SparkShower(pos, dir, count);
1133 MSG_ReadVector(pos);
1134 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1135 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1138 // LordHavoc: added for improved gore
1139 case TE_BLOODSHOWER:
1141 MSG_ReadVector(pos); // mins
1142 MSG_ReadVector(pos2); // maxs
1143 velspeed = MSG_ReadCoord (); // speed
1144 count = MSG_ReadShort (); // number of particles
1145 CL_BloodShower(pos, pos2, velspeed, count);
1147 case TE_PARTICLECUBE:
1148 // general purpose particle effect
1149 MSG_ReadVector(pos); // mins
1150 MSG_ReadVector(pos2); // maxs
1151 MSG_ReadVector(dir); // dir
1152 count = MSG_ReadShort (); // number of particles
1153 colorStart = MSG_ReadByte (); // color
1154 colorLength = MSG_ReadByte (); // gravity (1 or 0)
1155 velspeed = MSG_ReadCoord (); // randomvel
1156 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1159 case TE_PARTICLERAIN:
1160 // general purpose particle effect
1161 MSG_ReadVector(pos); // mins
1162 MSG_ReadVector(pos2); // maxs
1163 MSG_ReadVector(dir); // dir
1164 count = MSG_ReadShort (); // number of particles
1165 colorStart = MSG_ReadByte (); // color
1166 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1169 case TE_PARTICLESNOW:
1170 // general purpose particle effect
1171 MSG_ReadVector(pos); // mins
1172 MSG_ReadVector(pos2); // maxs
1173 MSG_ReadVector(dir); // dir
1174 count = MSG_ReadShort (); // number of particles
1175 colorStart = MSG_ReadByte (); // color
1176 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1180 // bullet hitting wall
1181 MSG_ReadVector(pos);
1182 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1183 // LordHavoc: changed to dust shower
1184 CL_SparkShower(pos, vec3_origin, 15);
1187 case TE_GUNSHOTQUAD:
1188 // quad bullet hitting wall
1189 MSG_ReadVector(pos);
1190 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1191 CL_SparkShower(pos, vec3_origin, 15);
1192 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1197 MSG_ReadVector(pos);
1198 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1199 CL_ParticleExplosion (pos);
1200 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1201 CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1202 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1205 case TE_EXPLOSIONQUAD:
1206 // quad rocket explosion
1207 MSG_ReadVector(pos);
1208 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1209 CL_ParticleExplosion (pos);
1210 CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1211 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1215 // Nehahra movie colored lighting explosion
1216 MSG_ReadVector(pos);
1217 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1218 CL_ParticleExplosion (pos);
1219 CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1220 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1223 case TE_EXPLOSIONRGB:
1224 // colored lighting explosion
1225 MSG_ReadVector(pos);
1226 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1227 CL_ParticleExplosion (pos);
1228 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1229 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1230 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1231 CL_AllocDlight (NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1232 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1235 case TE_TAREXPLOSION:
1236 // tarbaby explosion
1237 MSG_ReadVector(pos);
1238 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1239 CL_BlobExplosion (pos);
1241 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1242 CL_AllocDlight (NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
1243 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1247 MSG_ReadVector(pos);
1248 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1249 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1252 case TE_CUSTOMFLASH:
1253 MSG_ReadVector(pos);
1254 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1255 radius = MSG_ReadByte() * 8;
1256 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1257 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1258 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1259 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1260 CL_AllocDlight (NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1264 MSG_ReadVector(pos);
1265 MSG_ReadVector(dir);
1266 count = MSG_ReadByte();
1267 CL_Flames(pos, dir, count);
1273 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1274 CL_ParseBeam (cl_model_bolt, true);
1279 if (!cl_model_bolt2)
1280 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1281 CL_ParseBeam (cl_model_bolt2, true);
1286 if (!cl_model_bolt3)
1287 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1288 CL_ParseBeam (cl_model_bolt3, false);
1293 // grappling hook beam
1295 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1296 CL_ParseBeam (cl_model_beam, false);
1300 // LordHavoc: for compatibility with the Nehahra movie...
1301 case TE_LIGHTNING4NEH:
1302 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false), false);
1306 pos[0] = MSG_ReadCoord ();
1307 pos[1] = MSG_ReadCoord ();
1308 pos[2] = MSG_ReadCoord ();
1309 CL_LavaSplash (pos);
1313 pos[0] = MSG_ReadCoord ();
1314 pos[1] = MSG_ReadCoord ();
1315 pos[2] = MSG_ReadCoord ();
1316 CL_AllocDlight (NULL, pos, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f);
1317 // CL_TeleportSplash (pos);
1321 // color mapped explosion
1322 MSG_ReadVector(pos);
1323 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1324 colorStart = MSG_ReadByte ();
1325 colorLength = MSG_ReadByte ();
1326 CL_ParticleExplosion2 (pos, colorStart, colorLength);
1327 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1328 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);
1329 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1333 MSG_ReadVector(pos);
1334 MSG_ReadVector(pos2);
1335 MSG_ReadVector(dir);
1336 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1337 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1341 MSG_ReadVector(pos);
1342 MSG_ReadVector(dir);
1343 count = MSG_ReadByte ();
1344 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1345 CL_Tei_Smoke(pos, dir, count);
1348 case TE_TEI_BIGEXPLOSION:
1349 MSG_ReadVector(pos);
1350 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1351 CL_ParticleExplosion (pos);
1352 CL_AllocDlight (NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
1353 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1356 case TE_TEI_PLASMAHIT:
1357 MSG_ReadVector(pos);
1358 MSG_ReadVector(dir);
1359 count = MSG_ReadByte ();
1360 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 5);
1361 CL_Tei_PlasmaHit(pos, dir, count);
1362 CL_AllocDlight (NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
1366 Host_Error ("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1370 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1372 static qbyte cgamenetbuffer[65536];
1375 =====================
1376 CL_ParseServerMessage
1377 =====================
1379 int parsingerror = false;
1380 void CL_ParseServerMessage (void)
1383 int i, entitiesupdated;
1385 char *cmdlogname[32], *temp;
1386 int cmdindex, cmdcount = 0;
1389 // if recording demos, copy the message out
1391 if (cl_shownet.integer == 1)
1392 Con_Printf ("%i ",net_message.cursize);
1393 else if (cl_shownet.integer == 2)
1394 Con_Printf ("------------------\n");
1396 cl.onground = false; // unless the server says otherwise
1398 // parse the message
1400 MSG_BeginReading ();
1402 entitiesupdated = false;
1404 parsingerror = true;
1409 Host_Error ("CL_ParseServerMessage: Bad server message");
1411 cmd = MSG_ReadByte ();
1415 SHOWNET("END OF MESSAGE");
1416 break; // end of message
1419 cmdindex = cmdcount & 31;
1421 cmdlog[cmdindex] = cmd;
1423 // if the high bit of the command byte is set, it is a fast update
1426 // 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)
1428 cmdlogname[cmdindex] = temp;
1429 SHOWNET("fast update");
1430 if (cls.signon == SIGNONS - 1)
1432 // first update is the final signon stage
1433 cls.signon = SIGNONS;
1436 CL_ParseUpdate (cmd&127);
1440 SHOWNET(svc_strings[cmd]);
1441 cmdlogname[cmdindex] = svc_strings[cmd];
1442 if (!cmdlogname[cmdindex])
1444 // 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)
1446 cmdlogname[cmdindex] = temp;
1454 char description[32*64], temp[64];
1456 strcpy(description, "packet dump: ");
1460 count = cmdcount - i;
1464 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1465 strcat(description, temp);
1470 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1471 Con_Printf("%s", description);
1472 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1480 if (!entitiesupdated)
1482 // this is a new frame, we'll be seeing entities,
1483 // so prepare for entity updates
1484 CL_EntityUpdateSetup();
1485 entitiesupdated = true;
1487 cl.mtime[1] = cl.mtime[0];
1488 cl.mtime[0] = MSG_ReadFloat ();
1491 case svc_clientdata:
1492 i = MSG_ReadShort ();
1493 CL_ParseClientdata (i);
1497 i = MSG_ReadLong ();
1498 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1499 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1500 Nehahrademcompatibility = false;
1502 Nehahrademcompatibility = true;
1503 if (cls.demoplayback && demo_nehahra.integer)
1504 Nehahrademcompatibility = true;
1506 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1510 case svc_disconnect:
1511 Host_EndGame ("Server disconnected\n");
1514 Con_Printf ("%s", MSG_ReadString ());
1517 case svc_centerprint:
1518 SCR_CenterPrint (MSG_ReadString ());
1522 Cbuf_AddText (MSG_ReadString ());
1529 case svc_serverinfo:
1530 CL_ParseServerInfo ();
1534 for (i=0 ; i<3 ; i++)
1535 cl.viewangles[i] = MSG_ReadAngle ();
1539 cl.viewentity = MSG_ReadShort ();
1540 // LordHavoc: assume first setview recieved is the real player entity
1541 if (!cl.playerentity)
1542 cl.playerentity = cl.viewentity;
1545 case svc_lightstyle:
1546 i = MSG_ReadByte ();
1547 if (i >= MAX_LIGHTSTYLES)
1548 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1549 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1550 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1551 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1555 CL_ParseStartSoundPacket(false);
1559 CL_ParseStartSoundPacket(true);
1563 i = MSG_ReadShort();
1564 S_StopSound(i>>3, i&7);
1567 case svc_updatename:
1568 i = MSG_ReadByte ();
1569 if (i >= cl.maxclients)
1570 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1571 strcpy (cl.scores[i].name, MSG_ReadString ());
1574 case svc_updatefrags:
1575 i = MSG_ReadByte ();
1576 if (i >= cl.maxclients)
1577 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1578 cl.scores[i].frags = MSG_ReadShort ();
1581 case svc_updatecolors:
1582 i = MSG_ReadByte ();
1583 if (i >= cl.maxclients)
1584 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1585 cl.scores[i].colors = MSG_ReadByte ();
1589 CL_ParseParticleEffect ();
1600 case svc_spawnbaseline:
1601 i = MSG_ReadShort ();
1602 if (i < 0 || i >= MAX_EDICTS)
1603 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1604 CL_ParseBaseline (cl_entities + i, false);
1606 case svc_spawnbaseline2:
1607 i = MSG_ReadShort ();
1608 if (i < 0 || i >= MAX_EDICTS)
1609 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1610 CL_ParseBaseline (cl_entities + i, true);
1612 case svc_spawnstatic:
1613 CL_ParseStatic (false);
1615 case svc_spawnstatic2:
1616 CL_ParseStatic (true);
1618 case svc_temp_entity:
1619 CL_ParseTempEntity ();
1623 cl.paused = MSG_ReadByte ();
1631 i = MSG_ReadByte ();
1632 if (i <= cls.signon)
1633 Host_Error ("Received signon %i when at %i", i, cls.signon);
1638 case svc_killedmonster:
1639 cl.stats[STAT_MONSTERS]++;
1642 case svc_foundsecret:
1643 cl.stats[STAT_SECRETS]++;
1646 case svc_updatestat:
1647 i = MSG_ReadByte ();
1648 if (i < 0 || i >= MAX_CL_STATS)
1649 Host_Error ("svc_updatestat: %i is invalid", i);
1650 cl.stats[i] = MSG_ReadLong ();
1653 case svc_spawnstaticsound:
1654 CL_ParseStaticSound (false);
1657 case svc_spawnstaticsound2:
1658 CL_ParseStaticSound (true);
1662 cl.cdtrack = MSG_ReadByte ();
1663 cl.looptrack = MSG_ReadByte ();
1664 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1665 CDAudio_Play ((qbyte)cls.forcetrack, true);
1667 CDAudio_Play ((qbyte)cl.cdtrack, true);
1670 case svc_intermission:
1671 cl.intermission = 1;
1672 cl.completed_time = cl.time;
1676 cl.intermission = 2;
1677 cl.completed_time = cl.time;
1678 SCR_CenterPrint (MSG_ReadString ());
1682 cl.intermission = 3;
1683 cl.completed_time = cl.time;
1684 SCR_CenterPrint (MSG_ReadString ());
1687 case svc_sellscreen:
1688 Cmd_ExecuteString ("help", src_command);
1691 SHOWLMP_decodehide();
1694 SHOWLMP_decodeshow();
1697 R_SetSkyBox(MSG_ReadString());
1702 length = (int) ((unsigned short) MSG_ReadShort());
1703 for (i = 0;i < length;i++)
1704 cgamenetbuffer[i] = MSG_ReadByte();
1706 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1710 if (cls.signon == SIGNONS - 1)
1712 // first update is the final signon stage
1713 cls.signon = SIGNONS;
1716 CL_ReadEntityFrame();
1721 if (entitiesupdated)
1722 CL_EntityUpdateEnd();
1724 parsingerror = false;
1727 void CL_Parse_DumpPacket(void)
1731 Con_Printf("Packet dump:\n");
1732 SZ_HexDumpToConsole(&net_message);
1733 parsingerror = false;
1736 void CL_Parse_Init(void)
1738 // LordHavoc: added demo_nehahra cvar
1739 Cvar_RegisterVariable (&demo_nehahra);
1740 if (gamemode == GAME_NEHAHRA)
1741 Cvar_SetValue("demo_nehahra", 1);