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
102 mempool_t *cl_scores_mempool;
106 CL_ParseStartSoundPacket
109 void CL_ParseStartSoundPacket(int largesoundindex)
119 field_mask = MSG_ReadByte();
121 if (field_mask & SND_VOLUME)
122 volume = MSG_ReadByte ();
124 volume = DEFAULT_SOUND_PACKET_VOLUME;
126 if (field_mask & SND_ATTENUATION)
127 attenuation = MSG_ReadByte () / 64.0;
129 attenuation = DEFAULT_SOUND_PACKET_ATTENUATION;
131 if (field_mask & SND_LARGEENTITY)
133 ent = (unsigned short) MSG_ReadShort ();
134 channel = MSG_ReadByte ();
138 channel = (unsigned short) MSG_ReadShort ();
143 if (largesoundindex || field_mask & SND_LARGESOUND)
144 sound_num = (unsigned short) MSG_ReadShort ();
146 sound_num = MSG_ReadByte ();
148 if (sound_num >= MAX_SOUNDS)
149 Host_Error("CL_ParseStartSoundPacket: sound_num (%i) >= MAX_SOUNDS (%i)\n", sound_num, MAX_SOUNDS);
152 if (ent >= MAX_EDICTS)
153 Host_Error ("CL_ParseStartSoundPacket: ent = %i", ent);
155 for (i = 0;i < 3;i++)
156 pos[i] = MSG_ReadCoord ();
158 S_StartSound (ent, channel, cl.sound_precache[sound_num], pos, volume/255.0, attenuation);
165 When the client is taking a long time to load stuff, send keepalive messages
166 so the server doesn't disconnect.
170 static qbyte olddata[NET_MAXMESSAGE];
171 void CL_KeepaliveMessage (void)
174 static float lastmsg;
179 // no need if server is local and definitely not if this is a demo
180 if (sv.active || cls.demoplayback)
183 // read messages from server, should just be nops
184 oldreadcount = msg_readcount;
185 oldbadread = msg_badread;
187 memcpy(olddata, net_message.data, net_message.cursize);
189 NetConn_ClientFrame();
191 msg_readcount = oldreadcount;
192 msg_badread = oldbadread;
194 memcpy(net_message.data, olddata, net_message.cursize);
196 if (cls.netcon && NetConn_CanSendMessage(cls.netcon) && (time = Sys_DoubleTime()) - lastmsg >= 5)
200 Con_Printf("--> client to server keepalive\n");
201 MSG_WriteByte(&cls.message, clc_nop);
202 NetConn_SendReliableMessage(cls.netcon, &cls.message);
203 SZ_Clear(&cls.message);
204 // try not to utterly crush the computer with work, that's just rude
209 void CL_ParseEntityLump(char *entdata)
212 char key[128], value[4096];
213 FOG_clear(); // LordHavoc: no fog until set
214 R_SetSkyBox(""); // LordHavoc: no environment mapped sky until set
218 if (!COM_ParseToken(&data))
220 if (com_token[0] != '{')
224 if (!COM_ParseToken(&data))
226 if (com_token[0] == '}')
227 break; // end of worldspawn
228 if (com_token[0] == '_')
229 strcpy(key, com_token + 1);
231 strcpy(key, com_token);
232 while (key[strlen(key)-1] == ' ') // remove trailing spaces
233 key[strlen(key)-1] = 0;
234 if (!COM_ParseToken(&data))
236 strcpy(value, com_token);
237 if (!strcmp("sky", key))
239 else if (!strcmp("skyname", key)) // non-standard, introduced by QuakeForge... sigh.
241 else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK)
243 else if (!strcmp("fog", key))
244 sscanf(value, "%f %f %f %f", &fog_density, &fog_red, &fog_green, &fog_blue);
245 else if (!strcmp("fog_density", key))
246 fog_density = atof(value);
247 else if (!strcmp("fog_red", key))
248 fog_red = atof(value);
249 else if (!strcmp("fog_green", key))
250 fog_green = atof(value);
251 else if (!strcmp("fog_blue", key))
252 fog_blue = atof(value);
257 =====================
260 An svc_signonnum has been received, perform a client side setup
261 =====================
263 static void CL_SignonReply (void)
267 Con_DPrintf ("CL_SignonReply: %i\n", cls.signon);
272 MSG_WriteByte (&cls.message, clc_stringcmd);
273 MSG_WriteString (&cls.message, "prespawn");
277 MSG_WriteByte (&cls.message, clc_stringcmd);
278 MSG_WriteString (&cls.message, va("name \"%s\"\n", cl_name.string));
280 MSG_WriteByte (&cls.message, clc_stringcmd);
281 MSG_WriteString (&cls.message, va("color %i %i\n", cl_color.integer >> 4, cl_color.integer & 15));
283 if (cl_pmodel.integer)
285 MSG_WriteByte (&cls.message, clc_stringcmd);
286 MSG_WriteString (&cls.message, va("pmodel %i\n", cl_pmodel.integer));
289 MSG_WriteByte (&cls.message, clc_stringcmd);
290 MSG_WriteString (&cls.message, "spawn");
294 MSG_WriteByte (&cls.message, clc_stringcmd);
295 MSG_WriteString (&cls.message, "begin");
309 qbyte entlife[MAX_EDICTS];
310 // FIXME: this is a lot of memory to be keeping around, this needs to be dynamically allocated and freed
311 static char parse_model_precache[MAX_MODELS][MAX_QPATH];
312 static char parse_sound_precache[MAX_SOUNDS][MAX_QPATH];
313 void CL_ParseServerInfo (void)
317 int nummodels, numsounds;
320 Con_DPrintf ("Serverinfo packet received.\n");
322 // wipe the client_state_t struct
326 // parse protocol version number
328 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
330 Host_Error ("Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
333 Nehahrademcompatibility = false;
335 Nehahrademcompatibility = true;
336 if (cls.demoplayback && demo_nehahra.integer)
337 Nehahrademcompatibility = true;
339 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
343 cl.maxclients = MSG_ReadByte ();
344 if (cl.maxclients < 1 || cl.maxclients > MAX_SCOREBOARD)
346 Con_Printf("Bad maxclients (%u) from server\n", cl.maxclients);
349 Mem_EmptyPool(cl_scores_mempool);
350 cl.scores = Mem_Alloc(cl_scores_mempool, cl.maxclients*sizeof(*cl.scores));
353 cl.gametype = MSG_ReadByte ();
355 // parse signon message
356 str = MSG_ReadString ();
357 strncpy (cl.levelname, str, sizeof(cl.levelname)-1);
359 // seperate the printfs so the server message can have a color
360 if (!Nehahrademcompatibility) // no messages when playing the Nehahra movie
362 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");
363 Con_Printf ("%c%s\n", 2, str);
366 // check memory integrity
367 Mem_CheckSentinelsGlobal();
369 // disable until we get textures for it
372 memset (cl.model_precache, 0, sizeof(cl.model_precache));
373 memset (cl.sound_precache, 0, sizeof(cl.sound_precache));
375 // touch all of the precached models that are still loaded so we can free
376 // anything that isn't needed
378 for (nummodels=1 ; ; nummodels++)
380 CL_KeepaliveMessage ();
381 str = MSG_ReadString ();
384 if (nummodels==MAX_MODELS)
385 Host_Error ("Server sent too many model precaches\n");
386 if (strlen(str) >= MAX_QPATH)
387 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
388 strcpy (parse_model_precache[nummodels], str);
389 Mod_TouchModel (str);
392 // do the same for sounds
393 for (numsounds=1 ; ; numsounds++)
395 CL_KeepaliveMessage ();
396 str = MSG_ReadString ();
399 if (numsounds==MAX_SOUNDS)
400 Host_Error ("Server sent too many sound precaches\n");
401 if (strlen(str) >= MAX_QPATH)
402 Host_Error ("Server sent a precache name of %i characters (max %i)", strlen(str), MAX_QPATH - 1);
403 strcpy (parse_sound_precache[numsounds], str);
407 // purge anything that was not touched
410 // now we try to load everything that is new
413 CL_KeepaliveMessage ();
414 cl.model_precache[1] = Mod_ForName (parse_model_precache[1], false, false, true);
415 if (cl.model_precache[1] == NULL)
416 Con_Printf("Map %s not found\n", parse_model_precache[1]);
419 for (i=2 ; i<nummodels ; i++)
421 CL_KeepaliveMessage ();
422 if ((cl.model_precache[i] = Mod_ForName (parse_model_precache[i], false, false, false)) == NULL)
423 Con_Printf("Model %s not found\n", parse_model_precache[i]);
427 S_BeginPrecaching ();
428 for (i=1 ; i<numsounds ; i++)
430 CL_KeepaliveMessage ();
431 cl.sound_precache[i] = S_PrecacheSound (parse_sound_precache[i], true);
436 ent = &cl_entities[0];
437 // entire entity array was cleared, so just fill in a few fields
438 ent->state_current.active = true;
439 ent->render.model = cl.worldmodel = cl.model_precache[1];
440 //ent->render.scale = 1;
441 ent->render.alpha = 1;
442 ent->render.flags = RENDER_SHADOW;
443 Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, 0, 0, 0, 0, 0, 0, 1);
444 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
445 CL_BoundingBoxForEntity(&ent->render);
446 // clear entlife array
447 memset(entlife, 0, MAX_EDICTS);
454 // noclip is turned off at start
455 noclip_anglehack = false;
457 // check memory integrity
458 Mem_CheckSentinelsGlobal();
461 void CL_ValidateState(entity_state_t *s)
468 if (s->modelindex >= MAX_MODELS)
469 Host_Error("CL_ValidateState: modelindex (%i) >= MAX_MODELS (%i)\n", s->modelindex, MAX_MODELS);
471 // colormap is client index + 1
472 if (s->colormap > cl.maxclients)
473 Host_Error ("CL_ValidateState: colormap (%i) > cl.maxclients (%i)", s->colormap, cl.maxclients);
475 model = cl.model_precache[s->modelindex];
476 Mod_CheckLoaded(model);
477 if (model && s->frame >= model->numframes)
479 Con_DPrintf("CL_ValidateState: no such frame %i in \"%s\"\n", s->frame, model->name);
482 if (model && s->skin > 0 && s->skin >= model->numskins)
484 Con_DPrintf("CL_ValidateState: no such skin %i in \"%s\"\n", s->skin, model->name);
489 void CL_MoveLerpEntityStates(entity_t *ent)
491 float odelta[3], adelta[3];
492 VectorSubtract(ent->state_current.origin, ent->persistent.neworigin, odelta);
493 VectorSubtract(ent->state_current.angles, ent->persistent.newangles, adelta);
494 if (!ent->state_previous.active || cls.timedemo || DotProduct(odelta, odelta) > 1000*1000 || cl_nolerp.integer)
496 // we definitely shouldn't lerp
497 ent->persistent.lerpdeltatime = 0;
498 ent->persistent.lerpstarttime = cl.mtime[1];
499 VectorCopy(ent->state_current.origin, ent->persistent.oldorigin);
500 VectorCopy(ent->state_current.angles, ent->persistent.oldangles);
501 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
502 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
504 else if (ent->state_current.flags & RENDER_STEP)
506 // monster interpolation
507 if (DotProduct(odelta, odelta) + DotProduct(adelta, adelta) > 0.01)
509 ent->persistent.lerpdeltatime = bound(0, cl.mtime[1] - ent->persistent.lerpstarttime, 0.1);
510 ent->persistent.lerpstarttime = cl.mtime[1];
511 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
512 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
513 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
514 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
520 ent->persistent.lerpstarttime = cl.mtime[1];
521 // no lerp if it's singleplayer
522 if (sv.active && svs.maxclients == 1 && !ent->state_current.flags & RENDER_STEP)
523 ent->persistent.lerpdeltatime = 0;
525 ent->persistent.lerpdeltatime = cl.mtime[0] - cl.mtime[1];
526 VectorCopy(ent->persistent.neworigin, ent->persistent.oldorigin);
527 VectorCopy(ent->persistent.newangles, ent->persistent.oldangles);
528 VectorCopy(ent->state_current.origin, ent->persistent.neworigin);
529 VectorCopy(ent->state_current.angles, ent->persistent.newangles);
537 Parse an entity update message from the server
538 If an entities model or origin changes from frame to frame, it must be
539 relinked. Other attributes can change without relinking.
542 void CL_ParseUpdate (int bits)
548 if (bits & U_MOREBITS)
549 bits |= (MSG_ReadByte()<<8);
550 if ((bits & U_EXTEND1) && (!Nehahrademcompatibility))
552 bits |= MSG_ReadByte() << 16;
553 if (bits & U_EXTEND2)
554 bits |= MSG_ReadByte() << 24;
557 if (bits & U_LONGENTITY)
558 num = (unsigned) MSG_ReadShort ();
560 num = (unsigned) MSG_ReadByte ();
562 if (num >= MAX_EDICTS)
563 Host_Error("CL_ParseUpdate: entity number (%i) >= MAX_EDICTS (%i)\n", num, MAX_EDICTS);
565 Host_Error("CL_ParseUpdate: invalid entity number (%i)\n", num);
567 ent = cl_entities + num;
569 // note: this inherits the 'active' state of the baseline chosen
570 // (state_baseline is always active, state_current may not be active if
571 // the entity was missing in the last frame)
573 new = ent->state_current;
576 new = ent->state_baseline;
581 new.time = cl.mtime[0];
583 if (bits & U_MODEL) new.modelindex = (new.modelindex & 0xFF00) | MSG_ReadByte();
584 if (bits & U_FRAME) new.frame = (new.frame & 0xFF00) | MSG_ReadByte();
585 if (bits & U_COLORMAP) new.colormap = MSG_ReadByte();
586 if (bits & U_SKIN) new.skin = MSG_ReadByte();
587 if (bits & U_EFFECTS) new.effects = (new.effects & 0xFF00) | MSG_ReadByte();
588 if (bits & U_ORIGIN1) new.origin[0] = MSG_ReadCoord();
589 if (bits & U_ANGLE1) new.angles[0] = MSG_ReadAngle();
590 if (bits & U_ORIGIN2) new.origin[1] = MSG_ReadCoord();
591 if (bits & U_ANGLE2) new.angles[1] = MSG_ReadAngle();
592 if (bits & U_ORIGIN3) new.origin[2] = MSG_ReadCoord();
593 if (bits & U_ANGLE3) new.angles[2] = MSG_ReadAngle();
594 if (bits & U_STEP) new.flags |= RENDER_STEP;
595 if (bits & U_ALPHA) new.alpha = MSG_ReadByte();
596 if (bits & U_SCALE) new.scale = MSG_ReadByte();
597 if (bits & U_EFFECTS2) new.effects = (new.effects & 0x00FF) | (MSG_ReadByte() << 8);
598 if (bits & U_GLOWSIZE) new.glowsize = MSG_ReadByte();
599 if (bits & U_GLOWCOLOR) new.glowcolor = MSG_ReadByte();
600 // apparently the dpcrush demo uses this (unintended, and it uses white anyway)
601 if (bits & U_COLORMOD) MSG_ReadByte();
602 if (bits & U_GLOWTRAIL) new.flags |= RENDER_GLOWTRAIL;
603 if (bits & U_FRAME2) new.frame = (new.frame & 0x00FF) | (MSG_ReadByte() << 8);
604 if (bits & U_MODEL2) new.modelindex = (new.modelindex & 0x00FF) | (MSG_ReadByte() << 8);
605 if (bits & U_VIEWMODEL) new.flags |= RENDER_VIEWMODEL;
606 if (bits & U_EXTERIORMODEL) new.flags |= RENDER_EXTERIORMODEL;
608 // LordHavoc: to allow playback of the Nehahra movie
609 if (Nehahrademcompatibility && (bits & U_EXTEND1))
611 // LordHavoc: evil format
612 int i = MSG_ReadFloat();
613 int j = MSG_ReadFloat() * 255.0f;
618 new.effects |= EF_FULLBRIGHT;
622 else if (j == 0 || j >= 255)
629 CL_ValidateState(&new);
631 ent->state_previous = ent->state_current;
632 ent->state_current = new;
633 if (ent->state_current.active)
635 CL_MoveLerpEntityStates(ent);
636 cl_entities_active[ent->state_current.number] = true;
637 // mark as visible (no kill this frame)
638 entlife[ent->state_current.number] = 2;
642 static entity_frame_t entityframe;
643 void CL_ReadEntityFrame(void)
647 EntityFrame_Read(&cl.entitydatabase);
648 EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe);
649 for (i = 0;i < entityframe.numentities;i++)
652 ent = &cl_entities[entityframe.entitydata[i].number];
653 ent->state_previous = ent->state_current;
654 ent->state_current = entityframe.entitydata[i];
655 CL_MoveLerpEntityStates(ent);
656 // the entity lives again...
657 entlife[ent->state_current.number] = 2;
658 cl_entities_active[ent->state_current.number] = true;
662 void CL_EntityUpdateSetup(void)
666 void CL_EntityUpdateEnd(void)
669 // disable entities that disappeared this frame
670 for (i = 1;i < MAX_EDICTS;i++)
672 // clear only the entities that were active last frame but not this
673 // frame, don't waste time clearing all entities (which would cause
679 cl_entities[i].state_previous.active = cl_entities[i].state_current.active = 0;
689 void CL_ParseBaseline (entity_t *ent, int large)
693 memset(&ent->state_baseline, 0, sizeof(entity_state_t));
694 ent->state_baseline.active = true;
697 ent->state_baseline.modelindex = (unsigned short) MSG_ReadShort ();
698 ent->state_baseline.frame = (unsigned short) MSG_ReadShort ();
702 ent->state_baseline.modelindex = MSG_ReadByte ();
703 ent->state_baseline.frame = MSG_ReadByte ();
705 ent->state_baseline.colormap = MSG_ReadByte();
706 ent->state_baseline.skin = MSG_ReadByte();
707 for (i = 0;i < 3;i++)
709 ent->state_baseline.origin[i] = MSG_ReadCoord ();
710 ent->state_baseline.angles[i] = MSG_ReadAngle ();
712 ent->state_baseline.alpha = 255;
713 ent->state_baseline.scale = 16;
714 ent->state_baseline.glowsize = 0;
715 ent->state_baseline.glowcolor = 254;
716 ent->state_previous = ent->state_current = ent->state_baseline;
718 CL_ValidateState(&ent->state_baseline);
726 Server information pertaining to this client only
729 void CL_ParseClientdata (int bits)
734 if (bits & SU_EXTEND1)
735 bits |= (MSG_ReadByte() << 16);
736 if (bits & SU_EXTEND2)
737 bits |= (MSG_ReadByte() << 24);
739 if (bits & SU_VIEWHEIGHT)
740 cl.viewheight = MSG_ReadChar ();
742 cl.viewheight = DEFAULT_VIEWHEIGHT;
744 if (bits & SU_IDEALPITCH)
745 cl.idealpitch = MSG_ReadChar ();
749 VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
750 for (i=0 ; i<3 ; i++)
752 if (bits & (SU_PUNCH1<<i) )
755 cl.punchangle[i] = MSG_ReadPreciseAngle();
757 cl.punchangle[i] = MSG_ReadChar();
760 cl.punchangle[i] = 0;
761 if (bits & (SU_PUNCHVEC1<<i))
762 cl.punchvector[i] = MSG_ReadCoord();
764 cl.punchvector[i] = 0;
765 if (bits & (SU_VELOCITY1<<i) )
766 cl.mvelocity[0][i] = MSG_ReadChar()*16;
768 cl.mvelocity[0][i] = 0;
774 for (j=0 ; j<32 ; j++)
775 if ( (i & (1<<j)) && !(cl.items & (1<<j)))
776 cl.item_gettime[j] = cl.time;
780 cl.onground = (bits & SU_ONGROUND) != 0;
781 cl.inwater = (bits & SU_INWATER) != 0;
783 cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
784 cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
785 cl.stats[STAT_WEAPON] = (bits & SU_WEAPON) ? MSG_ReadByte() : 0;
786 cl.stats[STAT_HEALTH] = MSG_ReadShort();
787 cl.stats[STAT_AMMO] = MSG_ReadByte();
789 cl.stats[STAT_SHELLS] = MSG_ReadByte();
790 cl.stats[STAT_NAILS] = MSG_ReadByte();
791 cl.stats[STAT_ROCKETS] = MSG_ReadByte();
792 cl.stats[STAT_CELLS] = MSG_ReadByte();
796 if (gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE)
797 cl.stats[STAT_ACTIVEWEAPON] = (1<<i);
799 cl.stats[STAT_ACTIVEWEAPON] = i;
801 cl.viewzoomold = cl.viewzoomnew; // for interpolation
802 if (bits & SU_VIEWZOOM)
807 cl.viewzoomnew = (float) i * (1.0f / 255.0f);
815 =====================
817 =====================
819 void CL_ParseStatic (int large)
823 if (cl_num_static_entities >= cl_max_static_entities)
824 Host_Error ("Too many static entities");
825 ent = &cl_static_entities[cl_num_static_entities++];
826 CL_ParseBaseline (ent, large);
828 // copy it to the current state
829 ent->render.model = cl.model_precache[ent->state_baseline.modelindex];
830 ent->render.frame = ent->render.frame1 = ent->render.frame2 = ent->state_baseline.frame;
831 ent->render.framelerp = 0;
832 // make torchs play out of sync
833 ent->render.frame1time = ent->render.frame2time = lhrandom(-10, -1);
834 ent->render.colormap = -1; // no special coloring
835 ent->render.skinnum = ent->state_baseline.skin;
836 ent->render.effects = ent->state_baseline.effects;
837 ent->render.alpha = 1;
838 //ent->render.scale = 1;
840 //VectorCopy (ent->state_baseline.origin, ent->render.origin);
841 //VectorCopy (ent->state_baseline.angles, ent->render.angles);
843 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);
844 Matrix4x4_Invert_Simple(&ent->render.inversematrix, &ent->render.matrix);
845 CL_BoundingBoxForEntity(&ent->render);
847 // This is definitely cheating...
848 if (ent->render.model == NULL)
849 cl_num_static_entities--;
857 void CL_ParseStaticSound (int large)
860 int sound_num, vol, atten;
864 sound_num = (unsigned short) MSG_ReadShort ();
866 sound_num = MSG_ReadByte ();
867 vol = MSG_ReadByte ();
868 atten = MSG_ReadByte ();
870 S_StaticSound (cl.sound_precache[sound_num], org, vol, atten);
873 void CL_ParseEffect (void)
876 int modelindex, startframe, framecount, framerate;
879 modelindex = MSG_ReadByte ();
880 startframe = MSG_ReadByte ();
881 framecount = MSG_ReadByte ();
882 framerate = MSG_ReadByte ();
884 CL_Effect(org, modelindex, startframe, framecount, framerate);
887 void CL_ParseEffect2 (void)
890 int modelindex, startframe, framecount, framerate;
893 modelindex = MSG_ReadShort ();
894 startframe = MSG_ReadShort ();
895 framecount = MSG_ReadByte ();
896 framerate = MSG_ReadByte ();
898 CL_Effect(org, modelindex, startframe, framecount, framerate);
901 model_t *cl_model_bolt = NULL;
902 model_t *cl_model_bolt2 = NULL;
903 model_t *cl_model_bolt3 = NULL;
904 model_t *cl_model_beam = NULL;
906 sfx_t *cl_sfx_wizhit;
907 sfx_t *cl_sfx_knighthit;
912 sfx_t *cl_sfx_r_exp3;
919 void CL_InitTEnts (void)
921 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav", false);
922 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav", false);
923 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav", false);
924 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav", false);
925 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav", false);
926 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav", false);
927 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav", false);
930 void CL_ParseBeam (model_t *m, int lightning)
936 ent = MSG_ReadShort ();
937 MSG_ReadVector(start);
940 if (ent >= MAX_EDICTS)
942 Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent);
946 // override any beam with the same entity
947 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
949 if (b->entity == ent)
952 b->lightning = lightning;
953 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
955 b->endtime = cl.time + 0.2;
956 VectorCopy (start, b->start);
957 VectorCopy (end, b->end);
963 for (i = 0, b = cl_beams;i < cl_max_beams;i++, b++)
965 if (!b->model || b->endtime < cl.time)
968 b->lightning = lightning;
969 b->relativestartvalid = (ent && cl_entities[ent].state_current.active) ? 2 : 0;
971 b->endtime = cl.time + 0.2;
972 VectorCopy (start, b->start);
973 VectorCopy (end, b->end);
977 Con_Printf ("beam list overflow!\n");
980 void CL_ParseTempEntity (void)
988 int colorStart, colorLength, count;
989 float velspeed, radius;
992 type = MSG_ReadByte ();
996 // spike hitting wall
998 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
999 CL_AllocDlight (NULL, pos, 50, 0.25f, 1.00f, 0.25f, 250, 0.2);
1000 CL_RunParticleEffect (pos, vec3_origin, 20, 30);
1001 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
1004 case TE_KNIGHTSPIKE:
1005 // spike hitting wall
1006 MSG_ReadVector(pos);
1007 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1008 CL_AllocDlight (NULL, pos, 50, 1.0f, 0.60f, 0.20f, 250, 0.2);
1009 CL_RunParticleEffect (pos, vec3_origin, 226, 20);
1010 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
1014 // spike hitting wall
1015 MSG_ReadVector(pos);
1016 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1017 // LordHavoc: changed to spark shower
1018 CL_SparkShower(pos, vec3_origin, 15);
1020 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1025 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1027 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1029 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1033 // quad spike hitting wall
1034 MSG_ReadVector(pos);
1035 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1036 // LordHavoc: changed to spark shower
1037 CL_SparkShower(pos, vec3_origin, 15);
1038 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1039 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1041 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1046 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1048 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1050 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1054 // super spike hitting wall
1055 MSG_ReadVector(pos);
1056 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1057 // LordHavoc: changed to dust shower
1058 CL_SparkShower(pos, vec3_origin, 30);
1060 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1065 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1067 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1069 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1072 case TE_SUPERSPIKEQUAD:
1073 // quad super spike hitting wall
1074 MSG_ReadVector(pos);
1075 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1076 // LordHavoc: changed to dust shower
1077 CL_SparkShower(pos, vec3_origin, 30);
1078 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1080 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
1085 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
1087 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
1089 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
1092 // LordHavoc: added for improved blood splatters
1095 MSG_ReadVector(pos);
1096 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1097 dir[0] = MSG_ReadChar ();
1098 dir[1] = MSG_ReadChar ();
1099 dir[2] = MSG_ReadChar ();
1100 count = MSG_ReadByte ();
1101 CL_BloodPuff(pos, dir, count);
1105 MSG_ReadVector(pos);
1106 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1107 CL_BloodPuff(pos, vec3_origin, 10);
1111 MSG_ReadVector(pos);
1112 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1113 dir[0] = MSG_ReadChar ();
1114 dir[1] = MSG_ReadChar ();
1115 dir[2] = MSG_ReadChar ();
1116 count = MSG_ReadByte ();
1117 CL_SparkShower(pos, dir, count);
1120 MSG_ReadVector(pos);
1121 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1122 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1125 // LordHavoc: added for improved gore
1126 case TE_BLOODSHOWER:
1128 MSG_ReadVector(pos); // mins
1129 MSG_ReadVector(pos2); // maxs
1130 velspeed = MSG_ReadCoord (); // speed
1131 count = MSG_ReadShort (); // number of particles
1132 CL_BloodShower(pos, pos2, velspeed, count);
1134 case TE_PARTICLECUBE:
1135 // general purpose particle effect
1136 MSG_ReadVector(pos); // mins
1137 MSG_ReadVector(pos2); // maxs
1138 MSG_ReadVector(dir); // dir
1139 count = MSG_ReadShort (); // number of particles
1140 colorStart = MSG_ReadByte (); // color
1141 colorLength = MSG_ReadByte (); // gravity (1 or 0)
1142 velspeed = MSG_ReadCoord (); // randomvel
1143 CL_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
1146 case TE_PARTICLERAIN:
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 CL_ParticleRain(pos, pos2, dir, count, colorStart, 0);
1156 case TE_PARTICLESNOW:
1157 // general purpose particle effect
1158 MSG_ReadVector(pos); // mins
1159 MSG_ReadVector(pos2); // maxs
1160 MSG_ReadVector(dir); // dir
1161 count = MSG_ReadShort (); // number of particles
1162 colorStart = MSG_ReadByte (); // color
1163 CL_ParticleRain(pos, pos2, dir, count, colorStart, 1);
1167 // bullet hitting wall
1168 MSG_ReadVector(pos);
1169 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1170 // LordHavoc: changed to dust shower
1171 CL_SparkShower(pos, vec3_origin, 15);
1174 case TE_GUNSHOTQUAD:
1175 // quad bullet hitting wall
1176 MSG_ReadVector(pos);
1177 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1178 CL_SparkShower(pos, vec3_origin, 15);
1179 CL_AllocDlight (NULL, pos, 200, 0.1f, 0.1f, 1.0f, 1000, 0.2);
1184 MSG_ReadVector(pos);
1185 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1186 CL_ParticleExplosion (pos);
1187 // LordHavoc: boosted color from 1.0, 0.8, 0.4 to 1.25, 1.0, 0.5
1188 CL_AllocDlight (NULL, pos, 350, 1.25f, 1.0f, 0.5f, 700, 0.5);
1189 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1192 case TE_EXPLOSIONQUAD:
1193 // quad rocket explosion
1194 MSG_ReadVector(pos);
1195 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1196 CL_ParticleExplosion (pos);
1197 CL_AllocDlight (NULL, pos, 600, 0.5f, 0.4f, 1.0f, 1200, 0.5);
1198 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1202 // Nehahra movie colored lighting explosion
1203 MSG_ReadVector(pos);
1204 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1205 CL_ParticleExplosion (pos);
1206 CL_AllocDlight (NULL, pos, 350, MSG_ReadCoord(), MSG_ReadCoord(), MSG_ReadCoord(), 700, 0.5);
1207 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1210 case TE_EXPLOSIONRGB:
1211 // colored lighting explosion
1212 MSG_ReadVector(pos);
1213 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1214 CL_ParticleExplosion (pos);
1215 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1216 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1217 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1218 CL_AllocDlight (NULL, pos, 350, color[0], color[1], color[2], 700, 0.5);
1219 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1222 case TE_TAREXPLOSION:
1223 // tarbaby explosion
1224 MSG_ReadVector(pos);
1225 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1226 CL_BlobExplosion (pos);
1228 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1229 CL_AllocDlight (NULL, pos, 600, 0.8f, 0.4f, 1.0f, 1200, 0.5);
1230 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1234 MSG_ReadVector(pos);
1235 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1236 CL_AllocDlight (NULL, pos, 200, 1, 1, 1, 1000, 0.2);
1239 case TE_CUSTOMFLASH:
1240 MSG_ReadVector(pos);
1241 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1242 radius = MSG_ReadByte() * 8;
1243 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
1244 color[0] = MSG_ReadByte() * (1.0 / 255.0);
1245 color[1] = MSG_ReadByte() * (1.0 / 255.0);
1246 color[2] = MSG_ReadByte() * (1.0 / 255.0);
1247 CL_AllocDlight (NULL, pos, radius, color[0], color[1], color[2], radius / velspeed, velspeed);
1251 MSG_ReadVector(pos);
1252 MSG_ReadVector(dir);
1253 count = MSG_ReadByte();
1254 CL_Flames(pos, dir, count);
1260 cl_model_bolt = Mod_ForName("progs/bolt.mdl", true, false, false);
1261 CL_ParseBeam (cl_model_bolt, true);
1266 if (!cl_model_bolt2)
1267 cl_model_bolt2 = Mod_ForName("progs/bolt2.mdl", true, false, false);
1268 CL_ParseBeam (cl_model_bolt2, true);
1273 if (!cl_model_bolt3)
1274 cl_model_bolt3 = Mod_ForName("progs/bolt3.mdl", true, false, false);
1275 CL_ParseBeam (cl_model_bolt3, false);
1280 // grappling hook beam
1282 cl_model_beam = Mod_ForName("progs/beam.mdl", true, false, false);
1283 CL_ParseBeam (cl_model_beam, false);
1287 // LordHavoc: for compatibility with the Nehahra movie...
1288 case TE_LIGHTNING4NEH:
1289 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true, false, false), false);
1293 pos[0] = MSG_ReadCoord ();
1294 pos[1] = MSG_ReadCoord ();
1295 pos[2] = MSG_ReadCoord ();
1296 CL_LavaSplash (pos);
1300 pos[0] = MSG_ReadCoord ();
1301 pos[1] = MSG_ReadCoord ();
1302 pos[2] = MSG_ReadCoord ();
1303 CL_AllocDlight (NULL, pos, 500, 1.0f, 1.0f, 1.0f, 1500, 99.0f);
1304 // CL_TeleportSplash (pos);
1308 // color mapped explosion
1309 MSG_ReadVector(pos);
1310 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1311 colorStart = MSG_ReadByte ();
1312 colorLength = MSG_ReadByte ();
1313 CL_ParticleExplosion2 (pos, colorStart, colorLength);
1314 tempcolor = (qbyte *)&palette_complete[(rand()%colorLength) + colorStart];
1315 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);
1316 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1320 MSG_ReadVector(pos);
1321 MSG_ReadVector(pos2);
1322 MSG_ReadVector(dir);
1323 CL_BeamParticle(pos, pos2, 12, 1, 0.3, 0.1, 1, 1);
1324 CL_BeamParticle(pos, pos2, 5, 1, 0.9, 0.3, 1, 1);
1328 MSG_ReadVector(pos);
1329 MSG_ReadVector(dir);
1330 count = MSG_ReadByte ();
1331 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 4);
1332 CL_Tei_Smoke(pos, dir, count);
1335 case TE_TEI_BIGEXPLOSION:
1336 MSG_ReadVector(pos);
1337 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 10);
1338 CL_ParticleExplosion (pos);
1339 CL_AllocDlight (NULL, pos, 500, 1.25f, 1.0f, 0.5f, 500, 9999);
1340 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
1343 case TE_TEI_PLASMAHIT:
1344 MSG_ReadVector(pos);
1345 MSG_ReadVector(dir);
1346 count = MSG_ReadByte ();
1347 Mod_FindNonSolidLocation(pos, pos, cl.worldmodel, 5);
1348 CL_Tei_PlasmaHit(pos, dir, count);
1349 CL_AllocDlight (NULL, pos, 500, 0.3, 0.6, 1.0f, 2000, 9999);
1353 Host_Error ("CL_ParseTempEntity: bad type %d (hex %02X)", type, type);
1357 #define SHOWNET(x) if(cl_shownet.integer==2)Con_Printf ("%3i:%s\n", msg_readcount-1, x);
1359 static qbyte cgamenetbuffer[65536];
1362 =====================
1363 CL_ParseServerMessage
1364 =====================
1366 int parsingerror = false;
1367 void CL_ParseServerMessage(void)
1370 int i, entitiesupdated;
1372 char *cmdlogname[32], *temp;
1373 int cmdindex, cmdcount = 0;
1375 if (cls.demorecording)
1376 CL_WriteDemoMessage ();
1378 cl.last_received_message = realtime;
1381 // if recording demos, copy the message out
1383 if (cl_shownet.integer == 1)
1384 Con_Printf ("%f %i\n", realtime, net_message.cursize);
1385 else if (cl_shownet.integer == 2)
1386 Con_Printf ("------------------\n");
1388 cl.onground = false; // unless the server says otherwise
1390 // parse the message
1392 //MSG_BeginReading ();
1394 entitiesupdated = false;
1396 parsingerror = true;
1401 Host_Error ("CL_ParseServerMessage: Bad server message");
1403 cmd = MSG_ReadByte ();
1407 SHOWNET("END OF MESSAGE");
1408 break; // end of message
1411 cmdindex = cmdcount & 31;
1413 cmdlog[cmdindex] = cmd;
1415 // if the high bit of the command byte is set, it is a fast update
1418 // 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)
1420 cmdlogname[cmdindex] = temp;
1421 SHOWNET("fast update");
1422 if (cls.signon == SIGNONS - 1)
1424 // first update is the final signon stage
1425 cls.signon = SIGNONS;
1428 CL_ParseUpdate (cmd&127);
1432 SHOWNET(svc_strings[cmd]);
1433 cmdlogname[cmdindex] = svc_strings[cmd];
1434 if (!cmdlogname[cmdindex])
1436 // 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)
1438 cmdlogname[cmdindex] = temp;
1446 char description[32*64], temp[64];
1448 strcpy(description, "packet dump: ");
1452 count = cmdcount - i;
1456 sprintf(temp, "%3i:%s ", cmdlog[i], cmdlogname[i]);
1457 strcat(description, temp);
1462 description[strlen(description)-1] = '\n'; // replace the last space with a newline
1463 Con_Printf("%s", description);
1464 Host_Error ("CL_ParseServerMessage: Illegible server message\n");
1469 if (cls.signon < SIGNONS)
1470 Con_Printf("<-- server to client keepalive\n");
1474 if (!entitiesupdated)
1476 // this is a new frame, we'll be seeing entities,
1477 // so prepare for entity updates
1478 CL_EntityUpdateSetup();
1479 entitiesupdated = true;
1481 cl.mtime[1] = cl.mtime[0];
1482 cl.mtime[0] = MSG_ReadFloat ();
1485 case svc_clientdata:
1486 i = MSG_ReadShort ();
1487 CL_ParseClientdata (i);
1491 i = MSG_ReadLong ();
1492 if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != DPPROTOCOL_VERSION3 && i != 250)
1493 Host_Error ("CL_ParseServerMessage: Server is protocol %i, not %i, %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, DPPROTOCOL_VERSION3, PROTOCOL_VERSION);
1494 Nehahrademcompatibility = false;
1496 Nehahrademcompatibility = true;
1497 if (cls.demoplayback && demo_nehahra.integer)
1498 Nehahrademcompatibility = true;
1500 if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2 && dpprotocol != DPPROTOCOL_VERSION3)
1504 case svc_disconnect:
1505 Host_EndGame ("Server disconnected\n");
1508 Con_Printf ("%s", MSG_ReadString ());
1511 case svc_centerprint:
1512 SCR_CenterPrint (MSG_ReadString ());
1516 Cbuf_AddText (MSG_ReadString ());
1523 case svc_serverinfo:
1524 CL_ParseServerInfo ();
1528 for (i=0 ; i<3 ; i++)
1529 cl.viewangles[i] = MSG_ReadAngle ();
1533 cl.viewentity = MSG_ReadShort ();
1534 // LordHavoc: assume first setview recieved is the real player entity
1535 if (!cl.playerentity)
1536 cl.playerentity = cl.viewentity;
1539 case svc_lightstyle:
1540 i = MSG_ReadByte ();
1541 if (i >= MAX_LIGHTSTYLES)
1542 Host_Error ("svc_lightstyle >= MAX_LIGHTSTYLES");
1543 strncpy (cl_lightstyle[i].map, MSG_ReadString(), MAX_STYLESTRING - 1);
1544 cl_lightstyle[i].map[MAX_STYLESTRING - 1] = 0;
1545 cl_lightstyle[i].length = strlen(cl_lightstyle[i].map);
1549 CL_ParseStartSoundPacket(false);
1553 CL_ParseStartSoundPacket(true);
1557 i = MSG_ReadShort();
1558 S_StopSound(i>>3, i&7);
1561 case svc_updatename:
1562 i = MSG_ReadByte ();
1563 if (i >= cl.maxclients)
1564 Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients");
1565 strcpy (cl.scores[i].name, MSG_ReadString ());
1568 case svc_updatefrags:
1569 i = MSG_ReadByte ();
1570 if (i >= cl.maxclients)
1571 Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients");
1572 cl.scores[i].frags = MSG_ReadShort ();
1575 case svc_updatecolors:
1576 i = MSG_ReadByte ();
1577 if (i >= cl.maxclients)
1578 Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients");
1579 cl.scores[i].colors = MSG_ReadByte ();
1583 CL_ParseParticleEffect ();
1594 case svc_spawnbaseline:
1595 i = MSG_ReadShort ();
1596 if (i < 0 || i >= MAX_EDICTS)
1597 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline: invalid entity number %i", i);
1598 CL_ParseBaseline (cl_entities + i, false);
1600 case svc_spawnbaseline2:
1601 i = MSG_ReadShort ();
1602 if (i < 0 || i >= MAX_EDICTS)
1603 Host_Error ("CL_ParseServerMessage: svc_spawnbaseline2: invalid entity number %i", i);
1604 CL_ParseBaseline (cl_entities + i, true);
1606 case svc_spawnstatic:
1607 CL_ParseStatic (false);
1609 case svc_spawnstatic2:
1610 CL_ParseStatic (true);
1612 case svc_temp_entity:
1613 CL_ParseTempEntity ();
1617 cl.paused = MSG_ReadByte ();
1625 i = MSG_ReadByte ();
1626 if (i <= cls.signon)
1627 Host_Error ("Received signon %i when at %i", i, cls.signon);
1632 case svc_killedmonster:
1633 cl.stats[STAT_MONSTERS]++;
1636 case svc_foundsecret:
1637 cl.stats[STAT_SECRETS]++;
1640 case svc_updatestat:
1641 i = MSG_ReadByte ();
1642 if (i < 0 || i >= MAX_CL_STATS)
1643 Host_Error ("svc_updatestat: %i is invalid", i);
1644 cl.stats[i] = MSG_ReadLong ();
1647 case svc_spawnstaticsound:
1648 CL_ParseStaticSound (false);
1651 case svc_spawnstaticsound2:
1652 CL_ParseStaticSound (true);
1656 cl.cdtrack = MSG_ReadByte ();
1657 cl.looptrack = MSG_ReadByte ();
1658 if ( (cls.demoplayback || cls.demorecording) && (cls.forcetrack != -1) )
1659 CDAudio_Play ((qbyte)cls.forcetrack, true);
1661 CDAudio_Play ((qbyte)cl.cdtrack, true);
1664 case svc_intermission:
1665 cl.intermission = 1;
1666 cl.completed_time = cl.time;
1670 cl.intermission = 2;
1671 cl.completed_time = cl.time;
1672 SCR_CenterPrint (MSG_ReadString ());
1676 cl.intermission = 3;
1677 cl.completed_time = cl.time;
1678 SCR_CenterPrint (MSG_ReadString ());
1681 case svc_sellscreen:
1682 Cmd_ExecuteString ("help", src_command);
1685 SHOWLMP_decodehide();
1688 SHOWLMP_decodeshow();
1691 R_SetSkyBox(MSG_ReadString());
1696 length = (int) ((unsigned short) MSG_ReadShort());
1697 for (i = 0;i < length;i++)
1698 cgamenetbuffer[i] = MSG_ReadByte();
1700 CL_CGVM_ParseNetwork(cgamenetbuffer, length);
1704 if (cls.signon == SIGNONS - 1)
1706 // first update is the final signon stage
1707 cls.signon = SIGNONS;
1710 CL_ReadEntityFrame();
1715 if (entitiesupdated)
1716 CL_EntityUpdateEnd();
1718 parsingerror = false;
1721 void CL_Parse_DumpPacket(void)
1725 Con_Printf("Packet dump:\n");
1726 SZ_HexDumpToConsole(&net_message);
1727 parsingerror = false;
1730 void CL_Parse_Init(void)
1732 // LordHavoc: added demo_nehahra cvar
1733 cl_scores_mempool = Mem_AllocPool("client player info");
1734 Cvar_RegisterVariable (&demo_nehahra);
1735 if (gamemode == GAME_NEHAHRA)
1736 Cvar_SetValue("demo_nehahra", 1);